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/dist/compound.cjs CHANGED
@@ -28,7 +28,7 @@ module.exports = __toCommonJS(compound_exports);
28
28
 
29
29
  // src/components/ui/table/components/DataTable/DataTable.tsx
30
30
  var import_react_table3 = require("@tanstack/react-table");
31
- var import_react8 = require("react");
31
+ var import_react9 = require("react");
32
32
 
33
33
  // src/components/ui/table/components/DataTable/DataTableRow.tsx
34
34
  var import_react_table = require("@tanstack/react-table");
@@ -49,6 +49,7 @@ var DATA_TABLE_VIRTUAL_OVERSCAN = 8;
49
49
  var DATA_TABLE_COLUMN_SIZE = 150;
50
50
  var DATA_TABLE_COLUMN_MIN_SIZE = 40;
51
51
  var DATA_TABLE_COLUMN_MAX_SIZE = 800;
52
+ var DATA_TABLE_COLUMN_REORDER_THRESHOLD = 4;
52
53
 
53
54
  // src/components/ui/table/DataTableContext.tsx
54
55
  var import_react = require("react");
@@ -889,23 +890,49 @@ var useConvertTreeData = ({
889
890
  function getRowFieldValue(row, key) {
890
891
  return row[key];
891
892
  }
892
- function computeRowSpans(data, rowSpanKey) {
893
+ function normalizeRowSpanParent(value) {
894
+ if (!value) return [];
895
+ return typeof value === "string" ? [value] : [...value];
896
+ }
897
+ function toParentSpanList(parentSpans) {
898
+ if (!parentSpans?.length) return [];
899
+ const first = parentSpans[0];
900
+ if (!Array.isArray(first)) {
901
+ return [parentSpans];
902
+ }
903
+ return parentSpans;
904
+ }
905
+ function buildStartRowLookup(spans) {
906
+ const startRows = new Array(spans.length);
907
+ let origin = 0;
908
+ for (let i = 0; i < spans.length; i++) {
909
+ if ((spans[i]?.rowSpan ?? 1) > 0) origin = i;
910
+ startRows[i] = origin;
911
+ }
912
+ return startRows;
913
+ }
914
+ function sharesParentGroup(parentStartRows, rowIndex) {
915
+ if (parentStartRows.length === 0 || rowIndex <= 0) return true;
916
+ return parentStartRows.every(
917
+ (startRows) => startRows[rowIndex - 1] === startRows[rowIndex]
918
+ );
919
+ }
920
+ function computeRowSpans(data, rowSpanKey, parentSpans) {
893
921
  if (data.length === 0) return [];
922
+ const parentStartRows = toParentSpanList(parentSpans).map(buildStartRowLookup);
894
923
  const result = [];
895
924
  for (let index = 0; index < data.length; index++) {
896
925
  const currentValue = getRowFieldValue(data[index], rowSpanKey);
897
926
  const previousValue = index > 0 ? getRowFieldValue(data[index - 1], rowSpanKey) : void 0;
898
- if (index > 0 && currentValue === previousValue) {
927
+ if (index > 0 && currentValue === previousValue && sharesParentGroup(parentStartRows, index)) {
899
928
  result.push({ rowSpan: 0, isFirstInGroup: false });
900
929
  continue;
901
930
  }
902
931
  let span = 1;
903
932
  for (let nextIndex = index + 1; nextIndex < data.length; nextIndex++) {
904
- if (getRowFieldValue(data[nextIndex], rowSpanKey) === currentValue) {
905
- span++;
906
- } else {
907
- break;
908
- }
933
+ if (getRowFieldValue(data[nextIndex], rowSpanKey) !== currentValue) break;
934
+ if (!sharesParentGroup(parentStartRows, nextIndex)) break;
935
+ span++;
909
936
  }
910
937
  result.push({ rowSpan: span, isFirstInGroup: true });
911
938
  }
@@ -927,10 +954,50 @@ function resolveRowSpanAt(rowSpans, rowIndex) {
927
954
  }
928
955
  return { startRow: rowIndex, rowSpan: 1 };
929
956
  }
957
+ function findRowSpanColumn(spec, ref) {
958
+ return spec.find((column) => column.columnId === ref) ?? spec.find((column) => column.rowSpanKey === ref);
959
+ }
930
960
  function buildColumnRowSpanMap(data, columnKeys) {
931
961
  const map = /* @__PURE__ */ new Map();
932
- for (const { columnId, rowSpanKey } of columnKeys) {
933
- map.set(columnId, computeRowSpans(data, rowSpanKey));
962
+ const visiting = /* @__PURE__ */ new Set();
963
+ const warnedCycles = /* @__PURE__ */ new Set();
964
+ const virtualParents = /* @__PURE__ */ new Map();
965
+ const spansForColumn = (columnId) => {
966
+ const cached = map.get(columnId);
967
+ if (cached !== void 0) return cached;
968
+ const column = columnKeys.find((item) => item.columnId === columnId);
969
+ if (!column) return void 0;
970
+ if (visiting.has(columnId)) {
971
+ if (!warnedCycles.has(columnId)) {
972
+ warnedCycles.add(columnId);
973
+ console.warn(
974
+ `[rowSpan] rowSpanParent cycle detected at column "${columnId}"; dropping the cyclic parent reference.`
975
+ );
976
+ }
977
+ return void 0;
978
+ }
979
+ visiting.add(columnId);
980
+ const parentSpans = (column.rowSpanParent ?? []).map((ref) => spansForParentRef(ref)).filter((spans2) => Boolean(spans2));
981
+ visiting.delete(columnId);
982
+ const spans = computeRowSpans(
983
+ data,
984
+ column.rowSpanKey,
985
+ parentSpans.length > 0 ? parentSpans : void 0
986
+ );
987
+ map.set(columnId, spans);
988
+ return spans;
989
+ };
990
+ const spansForParentRef = (ref) => {
991
+ const parentColumn = findRowSpanColumn(columnKeys, ref);
992
+ if (parentColumn) return spansForColumn(parentColumn.columnId);
993
+ const cached = virtualParents.get(ref);
994
+ if (cached !== void 0) return cached;
995
+ const spans = computeRowSpans(data, ref);
996
+ virtualParents.set(ref, spans);
997
+ return spans;
998
+ };
999
+ for (const column of columnKeys) {
1000
+ spansForColumn(column.columnId);
934
1001
  }
935
1002
  return map;
936
1003
  }
@@ -946,7 +1013,8 @@ function collectRowSpanColumns(columns) {
946
1013
  if (!columnId || !columnDef.meta?.rowSpan) continue;
947
1014
  result.push({
948
1015
  columnId,
949
- rowSpanKey: columnDef.meta.rowSpanKey ?? columnId
1016
+ rowSpanKey: columnDef.meta.rowSpanKey ?? columnId,
1017
+ rowSpanParent: normalizeRowSpanParent(columnDef.meta.rowSpanParent)
950
1018
  });
951
1019
  }
952
1020
  };
@@ -1785,13 +1853,350 @@ function getMergedHeaderGroups(headerGroups) {
1785
1853
  }));
1786
1854
  }
1787
1855
 
1856
+ // src/components/ui/table/features/column-reorder/columnReorder.ts
1857
+ function getColumnDefId(column) {
1858
+ if (column.id != null && column.id !== "") return column.id;
1859
+ if ("accessorKey" in column && column.accessorKey != null) {
1860
+ return String(column.accessorKey);
1861
+ }
1862
+ return void 0;
1863
+ }
1864
+ function getColumnDefChildren(column) {
1865
+ if (!("columns" in column) || !Array.isArray(column.columns)) return void 0;
1866
+ if (column.columns.length === 0) return void 0;
1867
+ return column.columns;
1868
+ }
1869
+ function collectLeafColumnIds(columns) {
1870
+ const ids = [];
1871
+ for (const column of columns) {
1872
+ const children = getColumnDefChildren(column);
1873
+ if (children) {
1874
+ ids.push(...collectLeafColumnIds(children));
1875
+ continue;
1876
+ }
1877
+ const id = getColumnDefId(column);
1878
+ if (id) ids.push(id);
1879
+ }
1880
+ return ids;
1881
+ }
1882
+ function areColumnOrdersEqual(left, right) {
1883
+ if (left.length !== right.length) return false;
1884
+ return left.every((id, index) => id === right[index]);
1885
+ }
1886
+ function resolveLeafColumnOrder(columns, order) {
1887
+ const leafIds = collectLeafColumnIds(columns);
1888
+ if (!order?.length) return leafIds;
1889
+ const leafSet = new Set(leafIds);
1890
+ const seen = /* @__PURE__ */ new Set();
1891
+ const next = order.filter((id) => {
1892
+ if (!leafSet.has(id) || seen.has(id)) return false;
1893
+ seen.add(id);
1894
+ return true;
1895
+ });
1896
+ for (const id of leafIds) {
1897
+ if (!seen.has(id)) next.push(id);
1898
+ }
1899
+ return next;
1900
+ }
1901
+ function flattenColumnSlots(columns, group) {
1902
+ const slots = [];
1903
+ for (const column of columns) {
1904
+ const id = getColumnDefId(column);
1905
+ const children = getColumnDefChildren(column);
1906
+ if (children) {
1907
+ const nestedGroup = id ? { id, def: column } : group;
1908
+ slots.push(...flattenColumnSlots(children, nestedGroup));
1909
+ continue;
1910
+ }
1911
+ if (!id) continue;
1912
+ slots.push({ id, def: column, group });
1913
+ }
1914
+ return slots;
1915
+ }
1916
+ function rebuildColumnTree(slots) {
1917
+ const result = [];
1918
+ let index = 0;
1919
+ while (index < slots.length) {
1920
+ const slot = slots[index];
1921
+ if (!slot.group) {
1922
+ result.push(slot.def);
1923
+ index += 1;
1924
+ continue;
1925
+ }
1926
+ const groupId = slot.group.id;
1927
+ const children = [];
1928
+ while (index < slots.length && slots[index]?.group?.id === groupId) {
1929
+ children.push(slots[index].def);
1930
+ index += 1;
1931
+ }
1932
+ const firstChildId = children[0] ? getColumnDefId(children[0]) : groupId;
1933
+ result.push({
1934
+ ...slot.group.def,
1935
+ id: `${groupId}::${firstChildId}`,
1936
+ columns: children
1937
+ });
1938
+ }
1939
+ return result;
1940
+ }
1941
+ function applyLeafColumnOrder(columns, order) {
1942
+ const resolved = resolveLeafColumnOrder(columns, order);
1943
+ const defaultOrder = collectLeafColumnIds(columns);
1944
+ if (areColumnOrdersEqual(resolved, defaultOrder)) {
1945
+ return columns;
1946
+ }
1947
+ const byId = new Map(
1948
+ flattenColumnSlots(columns).map((slot) => [
1949
+ slot.id,
1950
+ slot
1951
+ ])
1952
+ );
1953
+ const ordered = [];
1954
+ for (const id of resolved) {
1955
+ const slot = byId.get(id);
1956
+ if (slot) ordered.push(slot);
1957
+ }
1958
+ return rebuildColumnTree(ordered);
1959
+ }
1960
+ function moveColumnIds(order, fromIds, targetIds, edge) {
1961
+ if (fromIds.length === 0 || targetIds.length === 0) return [...order];
1962
+ const fromSet = new Set(fromIds);
1963
+ if (targetIds.some((id) => fromSet.has(id))) return [...order];
1964
+ const rest = order.filter((id) => !fromSet.has(id));
1965
+ const anchorId = edge === "before" ? targetIds[0] : targetIds[targetIds.length - 1];
1966
+ const anchorIndex = rest.indexOf(anchorId);
1967
+ if (anchorIndex < 0) return [...order];
1968
+ const insertAt = edge === "before" ? anchorIndex : anchorIndex + 1;
1969
+ return [...rest.slice(0, insertAt), ...fromIds, ...rest.slice(insertAt)];
1970
+ }
1971
+ function resolveDropEdge(clientX, rect) {
1972
+ return clientX < rect.left + rect.width / 2 ? "before" : "after";
1973
+ }
1974
+ function parseReorderIds(value) {
1975
+ if (!value) return [];
1976
+ return value.split(",").filter(Boolean);
1977
+ }
1978
+ function serializeReorderIds(ids) {
1979
+ return ids.join(",");
1980
+ }
1981
+ function isColumnReorderable(meta) {
1982
+ return meta?.reorderable !== false;
1983
+ }
1984
+
1985
+ // src/components/ui/table/features/column-reorder/useColumnReorder.ts
1986
+ var import_react4 = require("react");
1987
+ function hitTestReorderHeader(table, clientX, clientY) {
1988
+ const headers = Array.from(
1989
+ table.querySelectorAll(
1990
+ "thead th[data-column-id][data-reorder-ids]"
1991
+ )
1992
+ );
1993
+ const containing = headers.find((element) => {
1994
+ const rect = element.getBoundingClientRect();
1995
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
1996
+ });
1997
+ if (containing) {
1998
+ return {
1999
+ columnId: containing.dataset.columnId ?? "",
2000
+ edge: resolveDropEdge(clientX, containing.getBoundingClientRect())
2001
+ };
2002
+ }
2003
+ const leaves = headers.filter(
2004
+ (element) => element.hasAttribute("data-reorder-leaf")
2005
+ );
2006
+ let match;
2007
+ for (const element of leaves) {
2008
+ const rect = element.getBoundingClientRect();
2009
+ if (clientX >= rect.left && clientX <= rect.right) {
2010
+ match = element;
2011
+ break;
2012
+ }
2013
+ }
2014
+ if (!match && leaves.length > 0) {
2015
+ const first = leaves[0].getBoundingClientRect();
2016
+ const last = leaves[leaves.length - 1].getBoundingClientRect();
2017
+ if (clientX < first.left) match = leaves[0];
2018
+ else if (clientX > last.right) match = leaves[leaves.length - 1];
2019
+ }
2020
+ if (!match) return null;
2021
+ return {
2022
+ columnId: match.dataset.columnId ?? "",
2023
+ edge: resolveDropEdge(clientX, match.getBoundingClientRect())
2024
+ };
2025
+ }
2026
+ function readTargetIds(table, columnId) {
2027
+ const element = table.querySelector(
2028
+ `thead th[data-column-id="${CSS.escape(columnId)}"]`
2029
+ );
2030
+ return parseReorderIds(element?.getAttribute("data-reorder-ids"));
2031
+ }
2032
+ function useColumnReorder(options) {
2033
+ const { enabled, columnOrder, onColumnOrderChange } = options;
2034
+ const sessionRef = (0, import_react4.useRef)(null);
2035
+ const columnOrderRef = (0, import_react4.useRef)(columnOrder);
2036
+ const onColumnOrderChangeRef = (0, import_react4.useRef)(onColumnOrderChange);
2037
+ const [draggingColumnId, setDraggingColumnId] = (0, import_react4.useState)(null);
2038
+ const [dropTarget, setDropTarget] = (0, import_react4.useState)(
2039
+ null
2040
+ );
2041
+ const dropTargetRef = (0, import_react4.useRef)(dropTarget);
2042
+ const previousUserSelectRef = (0, import_react4.useRef)(null);
2043
+ columnOrderRef.current = columnOrder;
2044
+ onColumnOrderChangeRef.current = onColumnOrderChange;
2045
+ dropTargetRef.current = dropTarget;
2046
+ const resetDrag = (0, import_react4.useCallback)(() => {
2047
+ sessionRef.current = null;
2048
+ setDraggingColumnId(null);
2049
+ setDropTarget(null);
2050
+ const backup = previousUserSelectRef.current;
2051
+ previousUserSelectRef.current = null;
2052
+ if (backup) {
2053
+ if (backup.value) {
2054
+ document.body.style.setProperty("user-select", backup.value, backup.priority);
2055
+ } else {
2056
+ document.body.style.removeProperty("user-select");
2057
+ }
2058
+ return;
2059
+ }
2060
+ document.body.style.removeProperty("user-select");
2061
+ }, []);
2062
+ (0, import_react4.useEffect)(() => {
2063
+ if (!enabled) resetDrag();
2064
+ }, [enabled, resetDrag]);
2065
+ (0, import_react4.useEffect)(() => {
2066
+ return () => {
2067
+ resetDrag();
2068
+ };
2069
+ }, [resetDrag]);
2070
+ const onHeaderPointerDown = (0, import_react4.useCallback)(
2071
+ (event, meta) => {
2072
+ if (!enabled || !meta.canDrag) return;
2073
+ if (event.button !== 0) return;
2074
+ if (event.pointerType === "mouse" && event.ctrlKey) return;
2075
+ const target = event.target;
2076
+ if (target instanceof Element && target.closest("[data-table-disable-cell-selection]")) {
2077
+ return;
2078
+ }
2079
+ const table = event.currentTarget.closest("table");
2080
+ if (!(table instanceof HTMLTableElement)) return;
2081
+ sessionRef.current = {
2082
+ pointerId: event.pointerId,
2083
+ startX: event.clientX,
2084
+ startY: event.clientY,
2085
+ columnId: meta.columnId,
2086
+ fromIds: meta.leafIds,
2087
+ table,
2088
+ active: false
2089
+ };
2090
+ },
2091
+ [enabled]
2092
+ );
2093
+ (0, import_react4.useEffect)(() => {
2094
+ if (!enabled) return;
2095
+ const onPointerMove = (event) => {
2096
+ const session = sessionRef.current;
2097
+ if (!session || event.pointerId !== session.pointerId) return;
2098
+ const deltaX = event.clientX - session.startX;
2099
+ const deltaY = event.clientY - session.startY;
2100
+ const distance = Math.hypot(deltaX, deltaY);
2101
+ if (!session.active) {
2102
+ if (distance < DATA_TABLE_COLUMN_REORDER_THRESHOLD) return;
2103
+ session.active = true;
2104
+ if (!previousUserSelectRef.current) {
2105
+ previousUserSelectRef.current = {
2106
+ value: document.body.style.getPropertyValue("user-select"),
2107
+ priority: document.body.style.getPropertyPriority("user-select")
2108
+ };
2109
+ }
2110
+ document.body.style.setProperty("user-select", "none");
2111
+ setDraggingColumnId(session.columnId);
2112
+ }
2113
+ event.preventDefault();
2114
+ const nextTarget = hitTestReorderHeader(
2115
+ session.table,
2116
+ event.clientX,
2117
+ event.clientY
2118
+ );
2119
+ if (!nextTarget || !nextTarget.columnId) {
2120
+ setDropTarget(null);
2121
+ return;
2122
+ }
2123
+ const targetIds = readTargetIds(session.table, nextTarget.columnId);
2124
+ const fromSet = new Set(session.fromIds);
2125
+ if (targetIds.some((id) => fromSet.has(id))) {
2126
+ setDropTarget(null);
2127
+ return;
2128
+ }
2129
+ setDropTarget((previous) => {
2130
+ if (previous?.columnId === nextTarget.columnId && previous.edge === nextTarget.edge) {
2131
+ return previous;
2132
+ }
2133
+ return nextTarget;
2134
+ });
2135
+ };
2136
+ const onPointerUp = (event) => {
2137
+ const session = sessionRef.current;
2138
+ if (!session || event.pointerId !== session.pointerId) {
2139
+ return;
2140
+ }
2141
+ if (session.active) {
2142
+ event.preventDefault();
2143
+ const target = dropTargetRef.current;
2144
+ if (target) {
2145
+ const targetIds = readTargetIds(session.table, target.columnId);
2146
+ const next = moveColumnIds(
2147
+ columnOrderRef.current,
2148
+ session.fromIds,
2149
+ targetIds,
2150
+ target.edge
2151
+ );
2152
+ onColumnOrderChangeRef.current(next);
2153
+ }
2154
+ const suppressClick = (clickEvent) => {
2155
+ clickEvent.preventDefault();
2156
+ clickEvent.stopPropagation();
2157
+ document.removeEventListener("click", suppressClick, true);
2158
+ };
2159
+ document.addEventListener("click", suppressClick, true);
2160
+ window.setTimeout(() => {
2161
+ document.removeEventListener("click", suppressClick, true);
2162
+ }, 0);
2163
+ }
2164
+ resetDrag();
2165
+ };
2166
+ const onPointerCancel = (event) => {
2167
+ const session = sessionRef.current;
2168
+ if (!session || event.pointerId !== session.pointerId) {
2169
+ return;
2170
+ }
2171
+ if (session.active) {
2172
+ event.preventDefault();
2173
+ }
2174
+ resetDrag();
2175
+ };
2176
+ document.addEventListener("pointermove", onPointerMove);
2177
+ document.addEventListener("pointerup", onPointerUp);
2178
+ document.addEventListener("pointercancel", onPointerCancel);
2179
+ return () => {
2180
+ document.removeEventListener("pointermove", onPointerMove);
2181
+ document.removeEventListener("pointerup", onPointerUp);
2182
+ document.removeEventListener("pointercancel", onPointerCancel);
2183
+ };
2184
+ }, [enabled, resetDrag]);
2185
+ return {
2186
+ isReordering: draggingColumnId != null,
2187
+ draggingColumnId,
2188
+ dropTarget,
2189
+ onHeaderPointerDown
2190
+ };
2191
+ }
2192
+
1788
2193
  // src/core/useGlideTable.ts
1789
2194
  var import_react_table2 = require("@tanstack/react-table");
1790
2195
  var import_react_virtual = require("@tanstack/react-virtual");
1791
- var import_react7 = require("react");
2196
+ var import_react8 = require("react");
1792
2197
 
1793
2198
  // src/components/ui/table/features/cell-edit/useCellEdit.ts
1794
- var import_react4 = require("react");
2199
+ var import_react5 = require("react");
1795
2200
 
1796
2201
  // src/components/ui/table/features/cell-render/commitCellValue.ts
1797
2202
  function commitCellValue({
@@ -1831,21 +2236,21 @@ function useCellEdit({
1831
2236
  onDataChange,
1832
2237
  onCellChange
1833
2238
  }) {
1834
- const [editingCell, setEditingCell] = (0, import_react4.useState)(null);
1835
- const [draftValue, setDraftValue] = (0, import_react4.useState)("");
1836
- const draftValueRef = (0, import_react4.useRef)(draftValue);
1837
- const editingCellRef = (0, import_react4.useRef)(editingCell);
1838
- (0, import_react4.useEffect)(() => {
2239
+ const [editingCell, setEditingCell] = (0, import_react5.useState)(null);
2240
+ const [draftValue, setDraftValue] = (0, import_react5.useState)("");
2241
+ const draftValueRef = (0, import_react5.useRef)(draftValue);
2242
+ const editingCellRef = (0, import_react5.useRef)(editingCell);
2243
+ (0, import_react5.useEffect)(() => {
1839
2244
  draftValueRef.current = draftValue;
1840
2245
  }, [draftValue]);
1841
- (0, import_react4.useEffect)(() => {
2246
+ (0, import_react5.useEffect)(() => {
1842
2247
  editingCellRef.current = editingCell;
1843
2248
  }, [editingCell]);
1844
- const cancelEdit = (0, import_react4.useCallback)(() => {
2249
+ const cancelEdit = (0, import_react5.useCallback)(() => {
1845
2250
  setEditingCell(null);
1846
2251
  setDraftValue("");
1847
2252
  }, []);
1848
- const commitEdit = (0, import_react4.useCallback)(
2253
+ const commitEdit = (0, import_react5.useCallback)(
1849
2254
  (raw) => {
1850
2255
  const current = editingCellRef.current;
1851
2256
  if (!current) return true;
@@ -1881,7 +2286,7 @@ function useCellEdit({
1881
2286
  },
1882
2287
  [cancelEdit, data, onCellChange, onDataChange, rows]
1883
2288
  );
1884
- const startEdit = (0, import_react4.useCallback)(
2289
+ const startEdit = (0, import_react5.useCallback)(
1885
2290
  (rowIndex, colIndex) => {
1886
2291
  const cell = rows[rowIndex]?.getVisibleCells()[colIndex];
1887
2292
  if (!cell || !isColumnEditable(cell.column.columnDef)) return;
@@ -2117,7 +2522,7 @@ function formatDefaultCellValue(value) {
2117
2522
  }
2118
2523
 
2119
2524
  // src/components/ui/table/features/cell-selection/useCellSelection.ts
2120
- var import_react5 = require("react");
2525
+ var import_react6 = require("react");
2121
2526
 
2122
2527
  // src/components/ui/table/features/cell-selection/copyData.ts
2123
2528
  function formatPrimitive(value) {
@@ -2396,15 +2801,15 @@ function useCellSelection({
2396
2801
  onRowsPaste,
2397
2802
  onCellNavigate
2398
2803
  }) {
2399
- const [dragState, setDragState] = (0, import_react5.useState)(INITIAL_DRAG_STATE);
2400
- const pendingPasteModeRef = (0, import_react5.useRef)(null);
2401
- const dragStateRef = (0, import_react5.useRef)(dragState);
2402
- const onCellNavigateRef = (0, import_react5.useRef)(onCellNavigate);
2804
+ const [dragState, setDragState] = (0, import_react6.useState)(INITIAL_DRAG_STATE);
2805
+ const pendingPasteModeRef = (0, import_react6.useRef)(null);
2806
+ const dragStateRef = (0, import_react6.useRef)(dragState);
2807
+ const onCellNavigateRef = (0, import_react6.useRef)(onCellNavigate);
2403
2808
  dragStateRef.current = dragState;
2404
2809
  onCellNavigateRef.current = onCellNavigate;
2405
2810
  const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
2406
2811
  const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
2407
- const handleCellMouseDown = (0, import_react5.useCallback)(
2812
+ const handleCellMouseDown = (0, import_react6.useCallback)(
2408
2813
  (rowIndex, colIndex, options) => {
2409
2814
  if (!enabled) return;
2410
2815
  setDragState((prev) => {
@@ -2430,7 +2835,7 @@ function useCellSelection({
2430
2835
  },
2431
2836
  [enabled]
2432
2837
  );
2433
- const handleCellMouseEnter = (0, import_react5.useCallback)(
2838
+ const handleCellMouseEnter = (0, import_react6.useCallback)(
2434
2839
  (rowIndex, colIndex) => {
2435
2840
  if (!enabled) return;
2436
2841
  setDragState((prev) => {
@@ -2445,7 +2850,7 @@ function useCellSelection({
2445
2850
  },
2446
2851
  [enabled]
2447
2852
  );
2448
- const handleFillHandleMouseDown = (0, import_react5.useCallback)(
2853
+ const handleFillHandleMouseDown = (0, import_react6.useCallback)(
2449
2854
  (rowIndex, colIndex) => {
2450
2855
  if (!enabled) return;
2451
2856
  setDragState((prev) => {
@@ -2462,12 +2867,12 @@ function useCellSelection({
2462
2867
  },
2463
2868
  [enabled]
2464
2869
  );
2465
- (0, import_react5.useEffect)(() => {
2870
+ (0, import_react6.useEffect)(() => {
2466
2871
  if (!enabled) {
2467
2872
  setDragState(INITIAL_DRAG_STATE);
2468
2873
  }
2469
2874
  }, [enabled]);
2470
- (0, import_react5.useEffect)(() => {
2875
+ (0, import_react6.useEffect)(() => {
2471
2876
  if (!enabled) return;
2472
2877
  const handleKeyDown = (e) => {
2473
2878
  if (e.ctrlKey || e.metaKey || e.altKey) return;
@@ -2514,7 +2919,7 @@ function useCellSelection({
2514
2919
  window.addEventListener("keydown", handleKeyDown);
2515
2920
  return () => window.removeEventListener("keydown", handleKeyDown);
2516
2921
  }, [columnCount, enabled, rows]);
2517
- const copySelection = (0, import_react5.useCallback)(
2922
+ const copySelection = (0, import_react6.useCallback)(
2518
2923
  async (options) => {
2519
2924
  if (!enabled || !activeSelectionBounds) return false;
2520
2925
  const mode = options?.includeDescendants && enableSubtreeCopy ? "subtree" : "visible";
@@ -2522,7 +2927,7 @@ function useCellSelection({
2522
2927
  },
2523
2928
  [activeSelectionBounds, enableSubtreeCopy, enabled, rows]
2524
2929
  );
2525
- (0, import_react5.useEffect)(() => {
2930
+ (0, import_react6.useEffect)(() => {
2526
2931
  if (!enabled) return;
2527
2932
  const handleKeyDown = (e) => {
2528
2933
  if (!activeSelectionBounds) return;
@@ -2536,7 +2941,7 @@ function useCellSelection({
2536
2941
  window.addEventListener("keydown", handleKeyDown);
2537
2942
  return () => window.removeEventListener("keydown", handleKeyDown);
2538
2943
  }, [activeSelectionBounds, copySelection, enableSubtreeCopy, enabled]);
2539
- const emitRowsPaste = (0, import_react5.useCallback)(
2944
+ const emitRowsPaste = (0, import_react6.useCallback)(
2540
2945
  (text, mode) => {
2541
2946
  if (!onRowsPaste || !activeSelectionBounds) return false;
2542
2947
  const payload = buildRowsPastePayload(
@@ -2553,7 +2958,7 @@ function useCellSelection({
2553
2958
  },
2554
2959
  [activeSelectionBounds, onRowsPaste, rows]
2555
2960
  );
2556
- (0, import_react5.useEffect)(() => {
2961
+ (0, import_react6.useEffect)(() => {
2557
2962
  if (!enabled || !onRowsPaste) return;
2558
2963
  const pasteHandledRef = { current: false };
2559
2964
  const ignoreNextPasteRef = { current: false };
@@ -2621,7 +3026,7 @@ function useCellSelection({
2621
3026
  enabled,
2622
3027
  onRowsPaste
2623
3028
  ]);
2624
- (0, import_react5.useEffect)(() => {
3029
+ (0, import_react6.useEffect)(() => {
2625
3030
  if (!enabled) return;
2626
3031
  const handleMouseUp = () => {
2627
3032
  setDragState((prev) => {
@@ -2672,7 +3077,7 @@ function useCellSelection({
2672
3077
  }
2673
3078
 
2674
3079
  // src/components/ui/table/features/inline-search/useInlineSearch.ts
2675
- var import_react6 = require("react");
3080
+ var import_react7 = require("react");
2676
3081
  var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
2677
3082
  function useInlineSearch({
2678
3083
  enabled = false,
@@ -2689,46 +3094,46 @@ function useInlineSearch({
2689
3094
  onNavigateToResult,
2690
3095
  rootRef
2691
3096
  }) {
2692
- const searchInputId = (0, import_react6.useId)();
2693
- const searchInputRef = (0, import_react6.useRef)(null);
2694
- const [internalShowSearch, setInternalShowSearch] = (0, import_react6.useState)(false);
2695
- const [internalSearchValue, setInternalSearchValue] = (0, import_react6.useState)("");
2696
- const [internalResults, setInternalResults] = (0, import_react6.useState)(
3097
+ const searchInputId = (0, import_react7.useId)();
3098
+ const searchInputRef = (0, import_react7.useRef)(null);
3099
+ const [internalShowSearch, setInternalShowSearch] = (0, import_react7.useState)(false);
3100
+ const [internalSearchValue, setInternalSearchValue] = (0, import_react7.useState)("");
3101
+ const [internalResults, setInternalResults] = (0, import_react7.useState)(
2697
3102
  []
2698
3103
  );
2699
- const [searchStatus, setSearchStatus] = (0, import_react6.useState)();
2700
- const searchStatusRef = (0, import_react6.useRef)(searchStatus);
3104
+ const [searchStatus, setSearchStatus] = (0, import_react7.useState)();
3105
+ const searchStatusRef = (0, import_react7.useRef)(searchStatus);
2701
3106
  searchStatusRef.current = searchStatus;
2702
- const abortControllerRef = (0, import_react6.useRef)(null);
2703
- const searchHandleRef = (0, import_react6.useRef)(void 0);
2704
- const initialStartRowRef = (0, import_react6.useRef)(initialStartRow);
3107
+ const abortControllerRef = (0, import_react7.useRef)(null);
3108
+ const searchHandleRef = (0, import_react7.useRef)(void 0);
3109
+ const initialStartRowRef = (0, import_react7.useRef)(initialStartRow);
2705
3110
  initialStartRowRef.current = initialStartRow;
2706
- const getCellValueRef = (0, import_react6.useRef)(getCellValue);
3111
+ const getCellValueRef = (0, import_react7.useRef)(getCellValue);
2707
3112
  getCellValueRef.current = getCellValue;
2708
3113
  const showSearch = controlledShowSearch ?? internalShowSearch;
2709
3114
  const searchValue = controlledSearchValue ?? internalSearchValue;
2710
3115
  const searchResults = controlledSearchResults ?? internalResults;
2711
- const setSearchValue = (0, import_react6.useCallback)(
3116
+ const setSearchValue = (0, import_react7.useCallback)(
2712
3117
  (value) => {
2713
3118
  setInternalSearchValue(value);
2714
3119
  onSearchValueChange?.(value);
2715
3120
  },
2716
3121
  [onSearchValueChange]
2717
3122
  );
2718
- const cancelSearch = (0, import_react6.useCallback)(() => {
3123
+ const cancelSearch = (0, import_react7.useCallback)(() => {
2719
3124
  if (searchHandleRef.current !== void 0) {
2720
3125
  window.cancelAnimationFrame(searchHandleRef.current);
2721
3126
  searchHandleRef.current = void 0;
2722
3127
  }
2723
3128
  abortControllerRef.current?.abort();
2724
3129
  }, []);
2725
- const emitResultsChanged = (0, import_react6.useCallback)(
3130
+ const emitResultsChanged = (0, import_react7.useCallback)(
2726
3131
  (results, navIndex) => {
2727
3132
  onSearchResultsChanged?.(results, navIndex);
2728
3133
  },
2729
3134
  [onSearchResultsChanged]
2730
3135
  );
2731
- const navigateToIndex = (0, import_react6.useCallback)(
3136
+ const navigateToIndex = (0, import_react7.useCallback)(
2732
3137
  (results, navIndex) => {
2733
3138
  if (onSearchResultsChanged) return;
2734
3139
  if (navIndex < 0 || navIndex >= results.length) return;
@@ -2738,7 +3143,7 @@ function useInlineSearch({
2738
3143
  },
2739
3144
  [onNavigateToResult, onSearchResultsChanged]
2740
3145
  );
2741
- const beginSearch = (0, import_react6.useCallback)(
3146
+ const beginSearch = (0, import_react7.useCallback)(
2742
3147
  (query) => {
2743
3148
  if (controlledSearchResults !== void 0) return;
2744
3149
  const totalRows = rowCount;
@@ -2810,12 +3215,12 @@ function useInlineSearch({
2810
3215
  rowCount
2811
3216
  ]
2812
3217
  );
2813
- const openSearch = (0, import_react6.useCallback)(() => {
3218
+ const openSearch = (0, import_react7.useCallback)(() => {
2814
3219
  if (controlledShowSearch === void 0) {
2815
3220
  setInternalShowSearch(true);
2816
3221
  }
2817
3222
  }, [controlledShowSearch]);
2818
- const closeSearch = (0, import_react6.useCallback)(() => {
3223
+ const closeSearch = (0, import_react7.useCallback)(() => {
2819
3224
  if (controlledShowSearch === void 0) {
2820
3225
  setInternalShowSearch(false);
2821
3226
  }
@@ -2830,7 +3235,7 @@ function useInlineSearch({
2830
3235
  emitResultsChanged,
2831
3236
  onSearchClose
2832
3237
  ]);
2833
- const goToNext = (0, import_react6.useCallback)(() => {
3238
+ const goToNext = (0, import_react7.useCallback)(() => {
2834
3239
  if (!searchStatus || searchStatus.results === 0) return;
2835
3240
  const newIndex = nextSearchIndex(
2836
3241
  searchStatus.selectedIndex,
@@ -2840,7 +3245,7 @@ function useInlineSearch({
2840
3245
  emitResultsChanged(searchResults, newIndex);
2841
3246
  navigateToIndex(searchResults, newIndex);
2842
3247
  }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
2843
- const goToPrevious = (0, import_react6.useCallback)(() => {
3248
+ const goToPrevious = (0, import_react7.useCallback)(() => {
2844
3249
  if (!searchStatus || searchStatus.results === 0) return;
2845
3250
  const newIndex = previousSearchIndex(
2846
3251
  searchStatus.selectedIndex,
@@ -2850,7 +3255,7 @@ function useInlineSearch({
2850
3255
  emitResultsChanged(searchResults, newIndex);
2851
3256
  navigateToIndex(searchResults, newIndex);
2852
3257
  }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
2853
- (0, import_react6.useEffect)(() => {
3258
+ (0, import_react7.useEffect)(() => {
2854
3259
  if (controlledSearchResults === void 0) return;
2855
3260
  if (controlledSearchResults.length > 0) {
2856
3261
  setSearchStatus((current) => ({
@@ -2862,7 +3267,7 @@ function useInlineSearch({
2862
3267
  setSearchStatus(void 0);
2863
3268
  }
2864
3269
  }, [controlledSearchResults, rowCount]);
2865
- (0, import_react6.useEffect)(() => {
3270
+ (0, import_react7.useEffect)(() => {
2866
3271
  if (!enabled) return;
2867
3272
  setSearchStatus(void 0);
2868
3273
  setInternalResults([]);
@@ -2875,7 +3280,7 @@ function useInlineSearch({
2875
3280
  cancelSearch();
2876
3281
  }
2877
3282
  }, [enabled, showSearch]);
2878
- (0, import_react6.useEffect)(() => {
3283
+ (0, import_react7.useEffect)(() => {
2879
3284
  if (!enabled || !showSearch) return;
2880
3285
  if (controlledSearchResults !== void 0) return;
2881
3286
  if (searchValue.trim() === "") {
@@ -2895,7 +3300,7 @@ function useInlineSearch({
2895
3300
  searchValue,
2896
3301
  showSearch
2897
3302
  ]);
2898
- (0, import_react6.useEffect)(() => {
3303
+ (0, import_react7.useEffect)(() => {
2899
3304
  if (!enabled) return;
2900
3305
  const handleKeyDown = (event) => {
2901
3306
  if (!(event.ctrlKey || event.metaKey)) return;
@@ -2922,12 +3327,12 @@ function useInlineSearch({
2922
3327
  window.addEventListener("keydown", handleKeyDown, true);
2923
3328
  return () => window.removeEventListener("keydown", handleKeyDown, true);
2924
3329
  }, [controlledShowSearch, enabled, rootRef, showSearch]);
2925
- (0, import_react6.useEffect)(() => () => cancelSearch(), [cancelSearch]);
2926
- const searchMatchKeys = (0, import_react6.useMemo)(
3330
+ (0, import_react7.useEffect)(() => () => cancelSearch(), [cancelSearch]);
3331
+ const searchMatchKeys = (0, import_react7.useMemo)(
2927
3332
  () => buildSearchMatchKeys(searchResults),
2928
3333
  [searchResults]
2929
3334
  );
2930
- const activeMatch = (0, import_react6.useMemo)(() => {
3335
+ const activeMatch = (0, import_react7.useMemo)(() => {
2931
3336
  if (!searchStatus || searchStatus.selectedIndex < 0) return null;
2932
3337
  return searchResults[searchStatus.selectedIndex] ?? null;
2933
3338
  }, [searchResults, searchStatus]);
@@ -2992,6 +3397,7 @@ var DEFAULT_DATA_TABLE_LABELS = {
2992
3397
  expandRow: "Expand row",
2993
3398
  collapseRow: "Collapse row",
2994
3399
  resizeColumn: "Resize column",
3400
+ reorderColumn: "Reorder column",
2995
3401
  searchPlaceholder: "Search\u2026",
2996
3402
  searchResultHint: "Type to search",
2997
3403
  searchPrevious: "Previous result",
@@ -3049,6 +3455,9 @@ function useGlideTable(options) {
3049
3455
  columnSizing: controlledColumnSizing,
3050
3456
  onColumnSizingChange,
3051
3457
  columnResizeMode = "onChange",
3458
+ enableColumnReorder = false,
3459
+ columnOrder: controlledColumnOrder,
3460
+ onColumnOrderChange,
3052
3461
  enableColumnFreeze = false,
3053
3462
  enableInlineSearch = false,
3054
3463
  showSearch,
@@ -3058,7 +3467,7 @@ function useGlideTable(options) {
3058
3467
  searchResults,
3059
3468
  onSearchResultsChanged
3060
3469
  } = options;
3061
- const labels = (0, import_react7.useMemo)(() => {
3470
+ const labels = (0, import_react8.useMemo)(() => {
3062
3471
  const resolved = resolveDataTableLabels(labelsProp);
3063
3472
  return {
3064
3473
  ...resolved,
@@ -3069,16 +3478,17 @@ function useGlideTable(options) {
3069
3478
  }, [labelsProp, emptyText, loadingText, selectionLabel]);
3070
3479
  const enableExpand = Boolean(toggleField);
3071
3480
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
3072
- const [internalRowSelection, setInternalRowSelection] = (0, import_react7.useState)({});
3073
- const [internalColumnSizing, setInternalColumnSizing] = (0, import_react7.useState)({});
3074
- const [internalExpandedRows, setInternalExpandedRows] = (0, import_react7.useState)(
3481
+ const [internalRowSelection, setInternalRowSelection] = (0, import_react8.useState)({});
3482
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react8.useState)({});
3483
+ const [internalColumnOrder, setInternalColumnOrder] = (0, import_react8.useState)([]);
3484
+ const [internalExpandedRows, setInternalExpandedRows] = (0, import_react8.useState)(
3075
3485
  () => /* @__PURE__ */ new Set()
3076
3486
  );
3077
- const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react7.useState)(null);
3078
- const scrollRef = (0, import_react7.useRef)(null);
3079
- const rootRef = (0, import_react7.useRef)(null);
3487
+ const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react8.useState)(null);
3488
+ const scrollRef = (0, import_react8.useRef)(null);
3489
+ const rootRef = (0, import_react8.useRef)(null);
3080
3490
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
3081
- (0, import_react7.useEffect)(() => {
3491
+ (0, import_react8.useEffect)(() => {
3082
3492
  if (enableVirtualization && enableRowSpan) {
3083
3493
  console.warn(
3084
3494
  "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
@@ -3091,8 +3501,23 @@ function useGlideTable(options) {
3091
3501
  internalRowSelection
3092
3502
  );
3093
3503
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
3504
+ const columnOrder = controlledColumnOrder ?? internalColumnOrder;
3505
+ const tableColumns = (0, import_react8.useMemo)(() => {
3506
+ if (!enableColumnReorder) return columns;
3507
+ return applyLeafColumnOrder(columns, columnOrder);
3508
+ }, [columnOrder, columns, enableColumnReorder]);
3509
+ const setColumnOrder = (0, import_react8.useCallback)(
3510
+ (next) => {
3511
+ if (onColumnOrderChange) {
3512
+ onColumnOrderChange(next);
3513
+ return;
3514
+ }
3515
+ setInternalColumnOrder(next);
3516
+ },
3517
+ [onColumnOrderChange]
3518
+ );
3094
3519
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
3095
- const handleExpandedRowsChange = (0, import_react7.useCallback)(
3520
+ const handleExpandedRowsChange = (0, import_react8.useCallback)(
3096
3521
  (next) => {
3097
3522
  if (onExpandedRowsChange) {
3098
3523
  onExpandedRowsChange(next);
@@ -3115,7 +3540,7 @@ function useGlideTable(options) {
3115
3540
  });
3116
3541
  const table = (0, import_react_table2.useReactTable)({
3117
3542
  data: tableData,
3118
- columns,
3543
+ columns: tableColumns,
3119
3544
  ...enableColumnResize ? {
3120
3545
  defaultColumn: {
3121
3546
  minSize: DATA_TABLE_COLUMN_MIN_SIZE,
@@ -3153,13 +3578,13 @@ function useGlideTable(options) {
3153
3578
  getCoreRowModel: (0, import_react_table2.getCoreRowModel)(),
3154
3579
  getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
3155
3580
  });
3156
- const rowSpanColumnKeys = (0, import_react7.useMemo)(() => {
3581
+ const rowSpanColumnKeys = (0, import_react8.useMemo)(() => {
3157
3582
  if (!enableRowSpan) return [];
3158
3583
  return collectRowSpanColumns(columns);
3159
3584
  }, [enableRowSpan, columns]);
3160
3585
  const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
3161
3586
  const primaryRowSpanColumnId = rowSpanColumnKeys[0]?.columnId;
3162
- const columnRowSpanMap = (0, import_react7.useMemo)(
3587
+ const columnRowSpanMap = (0, import_react8.useMemo)(
3163
3588
  () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
3164
3589
  [tableData, rowSpanColumnKeys]
3165
3590
  );
@@ -3168,7 +3593,7 @@ function useGlideTable(options) {
3168
3593
  const rows = table.getRowModel().rows;
3169
3594
  const columnCount = table.getAllLeafColumns().length || 1;
3170
3595
  const visibleLeafColumns = table.getVisibleLeafColumns();
3171
- const columnFreezeOffsets = (0, import_react7.useMemo)(() => {
3596
+ const columnFreezeOffsets = (0, import_react8.useMemo)(() => {
3172
3597
  if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
3173
3598
  return buildColumnFreezeOffsets(
3174
3599
  visibleLeafColumns.map((column) => ({
@@ -3188,14 +3613,14 @@ function useGlideTable(options) {
3188
3613
  const totalSize = rowVirtualizer.getTotalSize();
3189
3614
  const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
3190
3615
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
3191
- const selectedRowIndices = (0, import_react7.useMemo)(() => {
3616
+ const selectedRowIndices = (0, import_react8.useMemo)(() => {
3192
3617
  const indices = /* @__PURE__ */ new Set();
3193
3618
  for (const selectedRow of selectedRows) {
3194
3619
  indices.add(selectedRow.index);
3195
3620
  }
3196
3621
  return indices;
3197
3622
  }, [selectedRows]);
3198
- const scrollCellIntoView = (0, import_react7.useCallback)(
3623
+ const scrollCellIntoView = (0, import_react8.useCallback)(
3199
3624
  (rowIndex, colIndex, options2) => {
3200
3625
  const align = options2?.align ?? "nearest";
3201
3626
  const blockAlign = align === "center" ? "center" : "nearest";
@@ -3222,7 +3647,7 @@ function useGlideTable(options) {
3222
3647
  },
3223
3648
  [rowVirtualizer, shouldVirtualize]
3224
3649
  );
3225
- const handleCellNavigate = (0, import_react7.useCallback)(
3650
+ const handleCellNavigate = (0, import_react8.useCallback)(
3226
3651
  (position) => {
3227
3652
  scrollCellIntoView(position.row, position.col, { align: "nearest" });
3228
3653
  },
@@ -3255,11 +3680,11 @@ function useGlideTable(options) {
3255
3680
  commitEdit,
3256
3681
  cancelEdit
3257
3682
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
3258
- const cellRendererRegistry = (0, import_react7.useMemo)(
3683
+ const cellRendererRegistry = (0, import_react8.useMemo)(
3259
3684
  () => createCellRendererRegistry(cellRenderers),
3260
3685
  [cellRenderers]
3261
3686
  );
3262
- const commitRenderedCellValue = (0, import_react7.useCallback)(
3687
+ const commitRenderedCellValue = (0, import_react8.useCallback)(
3263
3688
  (rowId, columnId, value) => commitCellValue({
3264
3689
  data: tableData,
3265
3690
  rows,
@@ -3271,11 +3696,11 @@ function useGlideTable(options) {
3271
3696
  }),
3272
3697
  [onCellChange, onDataChange, rows, tableData]
3273
3698
  );
3274
- const getCellContext = (0, import_react7.useCallback)(
3699
+ const getCellContext = (0, import_react8.useCallback)(
3275
3700
  (cell) => withCellUpdate(cell.getContext(), commitRenderedCellValue),
3276
3701
  [commitRenderedCellValue]
3277
3702
  );
3278
- const handleCellMouseDownWithCommit = (0, import_react7.useCallback)(
3703
+ const handleCellMouseDownWithCommit = (0, import_react8.useCallback)(
3279
3704
  (rowIndex, colIndex, options2) => {
3280
3705
  const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
3281
3706
  if (editingCell && !isSameEditingCell && !commitEdit()) {
@@ -3285,7 +3710,7 @@ function useGlideTable(options) {
3285
3710
  },
3286
3711
  [commitEdit, editingCell, handleCellMouseDown]
3287
3712
  );
3288
- const navigateToSearchResult = (0, import_react7.useCallback)(
3713
+ const navigateToSearchResult = (0, import_react8.useCallback)(
3289
3714
  (item) => {
3290
3715
  const [colIndex, rowIndex] = item;
3291
3716
  handleCellMouseDownWithCommit(rowIndex, colIndex);
@@ -3293,7 +3718,7 @@ function useGlideTable(options) {
3293
3718
  },
3294
3719
  [handleCellMouseDownWithCommit, scrollCellIntoView]
3295
3720
  );
3296
- const resolveSearchRowId = (0, import_react7.useCallback)(
3721
+ const resolveSearchRowId = (0, import_react8.useCallback)(
3297
3722
  (row, index) => {
3298
3723
  if (getRowId) return getRowId(row, index);
3299
3724
  if (enableExpand) {
@@ -3317,7 +3742,7 @@ function useGlideTable(options) {
3317
3742
  },
3318
3743
  [enableExpand, getRowId, toggleField]
3319
3744
  );
3320
- const searchCorpus = (0, import_react7.useMemo)(() => {
3745
+ const searchCorpus = (0, import_react8.useMemo)(() => {
3321
3746
  if (!enableInlineSearch) return [];
3322
3747
  if (enableExpand && toggleField) {
3323
3748
  return buildTreeSearchCorpus(tableData, {
@@ -3333,16 +3758,16 @@ function useGlideTable(options) {
3333
3758
  tableData,
3334
3759
  toggleField
3335
3760
  ]);
3336
- const searchCorpusRef = (0, import_react7.useRef)(searchCorpus);
3761
+ const searchCorpusRef = (0, import_react8.useRef)(searchCorpus);
3337
3762
  searchCorpusRef.current = searchCorpus;
3338
- const visibleRowIndexById = (0, import_react7.useMemo)(() => {
3763
+ const visibleRowIndexById = (0, import_react8.useMemo)(() => {
3339
3764
  const map = /* @__PURE__ */ new Map();
3340
3765
  for (const row of rows) {
3341
3766
  map.set(resolveSearchRowId(row.original, row.index), row.index);
3342
3767
  }
3343
3768
  return map;
3344
3769
  }, [resolveSearchRowId, rows]);
3345
- const getSearchCellValue = (0, import_react7.useCallback)(
3770
+ const getSearchCellValue = (0, import_react8.useCallback)(
3346
3771
  (rowIndex, colIndex) => {
3347
3772
  const corpusRow = searchCorpusRef.current[rowIndex];
3348
3773
  const column = visibleLeafColumns[colIndex];
@@ -3365,14 +3790,14 @@ function useGlideTable(options) {
3365
3790
  },
3366
3791
  [rows, visibleLeafColumns, visibleRowIndexById]
3367
3792
  );
3368
- const pendingSearchNavRef = (0, import_react7.useRef)(null);
3369
- const focusSearchResult = (0, import_react7.useCallback)(
3793
+ const pendingSearchNavRef = (0, import_react8.useRef)(null);
3794
+ const focusSearchResult = (0, import_react8.useCallback)(
3370
3795
  (colIndex, visibleRowIndex) => {
3371
3796
  navigateToSearchResult([colIndex, visibleRowIndex]);
3372
3797
  },
3373
3798
  [navigateToSearchResult]
3374
3799
  );
3375
- const navigateToCorpusSearchResult = (0, import_react7.useCallback)(
3800
+ const navigateToCorpusSearchResult = (0, import_react8.useCallback)(
3376
3801
  (item) => {
3377
3802
  const [colIndex, corpusRowIndex] = item;
3378
3803
  const corpusRow = searchCorpusRef.current[corpusRowIndex];
@@ -3405,7 +3830,7 @@ function useGlideTable(options) {
3405
3830
  visibleRowIndexById
3406
3831
  ]
3407
3832
  );
3408
- (0, import_react7.useEffect)(() => {
3833
+ (0, import_react8.useEffect)(() => {
3409
3834
  const pending = pendingSearchNavRef.current;
3410
3835
  if (!pending) return;
3411
3836
  const visibleRowIndex = visibleRowIndexById.get(pending.rowId);
@@ -3429,7 +3854,7 @@ function useGlideTable(options) {
3429
3854
  onNavigateToResult: navigateToCorpusSearchResult,
3430
3855
  rootRef
3431
3856
  });
3432
- const visibleSearchMatchKeys = (0, import_react7.useMemo)(() => {
3857
+ const visibleSearchMatchKeys = (0, import_react8.useMemo)(() => {
3433
3858
  if (!enableInlineSearch) return EMPTY_SEARCH_MATCH_KEYS;
3434
3859
  return mapSearchResultsToVisibleKeys(
3435
3860
  inlineSearch.searchResults,
@@ -3442,7 +3867,7 @@ function useGlideTable(options) {
3442
3867
  searchCorpus,
3443
3868
  visibleRowIndexById
3444
3869
  ]);
3445
- const visibleActiveMatch = (0, import_react7.useMemo)(() => {
3870
+ const visibleActiveMatch = (0, import_react8.useMemo)(() => {
3446
3871
  if (!enableInlineSearch || !inlineSearch.activeMatch) return null;
3447
3872
  return mapSearchResultToVisibleItem(
3448
3873
  inlineSearch.activeMatch,
@@ -3455,13 +3880,13 @@ function useGlideTable(options) {
3455
3880
  searchCorpus,
3456
3881
  visibleRowIndexById
3457
3882
  ]);
3458
- const clearHover = (0, import_react7.useCallback)(() => {
3883
+ const clearHover = (0, import_react8.useCallback)(() => {
3459
3884
  setHoveredRowIndex(null);
3460
3885
  }, []);
3461
- const handleRowHover = (0, import_react7.useCallback)((rowIndex, _rowData) => {
3886
+ const handleRowHover = (0, import_react8.useCallback)((rowIndex, _rowData) => {
3462
3887
  setHoveredRowIndex(rowIndex);
3463
3888
  }, []);
3464
- const handleToggleSelect = (0, import_react7.useCallback)(
3889
+ const handleToggleSelect = (0, import_react8.useCallback)(
3465
3890
  (row) => {
3466
3891
  if (!row.getCanSelect()) return;
3467
3892
  if (preserveRowSelection && row.getIsSelected()) {
@@ -3471,14 +3896,14 @@ function useGlideTable(options) {
3471
3896
  },
3472
3897
  [preserveRowSelection]
3473
3898
  );
3474
- const handleToggleExpand = (0, import_react7.useCallback)(
3899
+ const handleToggleExpand = (0, import_react8.useCallback)(
3475
3900
  (rowKey) => {
3476
3901
  if (preventExpand) return;
3477
3902
  handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
3478
3903
  },
3479
3904
  [preventExpand, handleExpandedRowsChange, expandedRows]
3480
3905
  );
3481
- const rowContextValue = (0, import_react7.useMemo)(() => {
3906
+ const rowContextValue = (0, import_react8.useMemo)(() => {
3482
3907
  return {
3483
3908
  rowSpan: {
3484
3909
  enableRowSpan,
@@ -3577,12 +4002,12 @@ function useGlideTable(options) {
3577
4002
  visibleSearchMatchKeys,
3578
4003
  visibleActiveMatch
3579
4004
  ]);
3580
- const copySelectionRef = (0, import_react7.useRef)(copySelection);
3581
- (0, import_react7.useEffect)(() => {
4005
+ const copySelectionRef = (0, import_react8.useRef)(copySelection);
4006
+ (0, import_react8.useEffect)(() => {
3582
4007
  copySelectionRef.current = copySelection;
3583
4008
  }, [copySelection]);
3584
- const stableCopySelection = (0, import_react7.useCallback)((options2) => copySelectionRef.current(options2), []);
3585
- (0, import_react7.useEffect)(() => {
4009
+ const stableCopySelection = (0, import_react8.useCallback)((options2) => copySelectionRef.current(options2), []);
4010
+ (0, import_react8.useEffect)(() => {
3586
4011
  onCopyActionsReady?.({ copySelection: stableCopySelection });
3587
4012
  }, [onCopyActionsReady, stableCopySelection]);
3588
4013
  return {
@@ -3597,6 +4022,7 @@ function useGlideTable(options) {
3597
4022
  selectionLabel: labels.selection,
3598
4023
  enableCellSelection,
3599
4024
  enableColumnResize,
4025
+ enableColumnReorder,
3600
4026
  enableColumnFreeze,
3601
4027
  enableInlineSearch,
3602
4028
  shouldVirtualize,
@@ -3610,6 +4036,7 @@ function useGlideTable(options) {
3610
4036
  getCellContext,
3611
4037
  handleToggleSelect,
3612
4038
  clearHover,
4039
+ setColumnOrder,
3613
4040
  copySelection: stableCopySelection,
3614
4041
  inlineSearch: {
3615
4042
  showSearch: inlineSearch.showSearch,
@@ -3693,6 +4120,7 @@ function DataTable({
3693
4120
  selectionLabel,
3694
4121
  enableCellSelection,
3695
4122
  enableColumnResize,
4123
+ enableColumnReorder,
3696
4124
  enableColumnFreeze,
3697
4125
  enableInlineSearch,
3698
4126
  shouldVirtualize,
@@ -3705,6 +4133,7 @@ function DataTable({
3705
4133
  rowContextValue,
3706
4134
  handleToggleSelect,
3707
4135
  clearHover,
4136
+ setColumnOrder,
3708
4137
  inlineSearch
3709
4138
  } = useGlideTable(glideOptions);
3710
4139
  const ToolbarSlot = slots?.Toolbar ?? DataTableToolbar;
@@ -3714,7 +4143,13 @@ function DataTable({
3714
4143
  const EmptySlot = slots?.Empty ?? DefaultEmpty;
3715
4144
  const freezeOffsets = rowContextValue.columnFreeze.offsets;
3716
4145
  const headerGroups = getMergedHeaderGroups(table.getHeaderGroups());
3717
- const contextValue = (0, import_react8.useMemo)(
4146
+ const leafColumnIds = table.getVisibleLeafColumns().map((column) => column.id);
4147
+ const { isReordering, draggingColumnId, dropTarget, onHeaderPointerDown } = useColumnReorder({
4148
+ enabled: enableColumnReorder,
4149
+ columnOrder: leafColumnIds,
4150
+ onColumnOrderChange: setColumnOrder
4151
+ });
4152
+ const contextValue = (0, import_react9.useMemo)(
3718
4153
  () => ({ ...rowContextValue, classNames }),
3719
4154
  [rowContextValue, classNames]
3720
4155
  );
@@ -3736,6 +4171,8 @@ function DataTable({
3736
4171
  "DataTableJSX",
3737
4172
  !enableCellSelection && "DataTableJSX--no-cell-selection",
3738
4173
  enableColumnResize && "DataTableJSX--column-resize",
4174
+ enableColumnReorder && "DataTableJSX--column-reorder",
4175
+ isReordering && "DataTableJSX--column-reordering",
3739
4176
  enableColumnFreeze && "DataTableJSX--column-freeze",
3740
4177
  enableInlineSearch && "DataTableJSX--inline-search",
3741
4178
  classNames?.root,
@@ -3804,20 +4241,43 @@ function DataTable({
3804
4241
  ...sizeStyle,
3805
4242
  ...freezeStyle
3806
4243
  };
4244
+ const isPlaceholder = header.isPlaceholder;
4245
+ const leafColumns = header.column.getLeafColumns();
4246
+ const leafIds = leafColumns.map((leafColumn) => leafColumn.id);
4247
+ const isLeafHeader = !isPlaceholder && header.subHeaders.length === 0;
4248
+ const canDrag = enableColumnReorder && !isPlaceholder && leafIds.length > 0 && leafColumns.every(
4249
+ (leafColumn) => isColumnReorderable(leafColumn.columnDef.meta)
4250
+ );
4251
+ const isDragging = draggingColumnId === header.column.id;
4252
+ const dropEdge = !isPlaceholder && dropTarget?.columnId === header.column.id ? dropTarget.edge : void 0;
3807
4253
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
3808
4254
  "th",
3809
4255
  {
3810
4256
  colSpan: header.colSpan,
3811
4257
  rowSpan: header.mergedRowSpan,
4258
+ "data-column-id": enableColumnReorder && !isPlaceholder ? header.column.id : void 0,
4259
+ "data-reorder-ids": enableColumnReorder && !isPlaceholder ? serializeReorderIds(leafIds) : void 0,
4260
+ "data-reorder-leaf": enableColumnReorder && isLeafHeader ? "" : void 0,
4261
+ "data-reorderable": canDrag ? "" : void 0,
4262
+ "data-reordering": isDragging ? "" : void 0,
4263
+ "data-drop-edge": dropEdge,
3812
4264
  "data-resizing": header.column.getIsResizing() ? "" : void 0,
3813
4265
  "data-frozen": freezeOffset?.side,
3814
4266
  "data-freeze-edge": getColumnFreezeEdgeAttr(freezeOffset),
4267
+ "aria-grabbed": isDragging ? true : void 0,
4268
+ title: canDrag ? labels.reorderColumn : void 0,
4269
+ onPointerDown: enableColumnReorder ? (event) => onHeaderPointerDown(event, {
4270
+ columnId: header.column.id,
4271
+ leafIds,
4272
+ canDrag
4273
+ }) : void 0,
3815
4274
  style: Object.keys(headerStyle).length > 0 ? headerStyle : void 0,
3816
4275
  className: cn(
3817
4276
  "data-table-head-cell",
3818
4277
  freezeOffset && `data-table-head-cell--frozen-${freezeOffset.side}`,
3819
4278
  CELL_ALIGN_CLASS[align],
3820
4279
  classNames?.headCell,
4280
+ dropEdge && classNames?.dropEdge,
3821
4281
  headerClassName
3822
4282
  ),
3823
4283
  children: [
@@ -3939,10 +4399,10 @@ function DataTable({
3939
4399
  }
3940
4400
 
3941
4401
  // src/components/ui/table/components/Table/Table.tsx
3942
- var import_react12 = require("react");
4402
+ var import_react13 = require("react");
3943
4403
 
3944
4404
  // src/components/ui/table/features/cell-render/ResolvedTableCell.tsx
3945
- var import_react9 = require("react");
4405
+ var import_react10 = require("react");
3946
4406
  function ResolvedTableCell({
3947
4407
  info
3948
4408
  }) {
@@ -3951,7 +4411,7 @@ function ResolvedTableCell({
3951
4411
  const meta = column.columnDef.meta;
3952
4412
  const value = getValue();
3953
4413
  const columnId = column.id;
3954
- const update = (0, import_react9.useCallback)(
4414
+ const update = (0, import_react10.useCallback)(
3955
4415
  (next) => {
3956
4416
  cellRender.commitValue(row.id, columnId, next);
3957
4417
  },
@@ -4011,10 +4471,12 @@ function buildColumnDef(props, sort, onSort) {
4011
4471
  minWidth,
4012
4472
  maxWidth,
4013
4473
  resizable,
4474
+ reorderable,
4014
4475
  frozen,
4015
4476
  align,
4016
4477
  rowSpan,
4017
4478
  rowSpanKey,
4479
+ rowSpanParent,
4018
4480
  editable,
4019
4481
  editType,
4020
4482
  editInputProps,
@@ -4049,6 +4511,7 @@ function buildColumnDef(props, sort, onSort) {
4049
4511
  align,
4050
4512
  rowSpan,
4051
4513
  rowSpanKey,
4514
+ rowSpanParent,
4052
4515
  editable,
4053
4516
  editType,
4054
4517
  editInputProps,
@@ -4056,6 +4519,7 @@ function buildColumnDef(props, sort, onSort) {
4056
4519
  cellProps,
4057
4520
  cellRender: render,
4058
4521
  frozen,
4522
+ reorderable,
4059
4523
  className,
4060
4524
  headerClassName
4061
4525
  }
@@ -4101,10 +4565,10 @@ function countLeafColumns(nodes) {
4101
4565
  }
4102
4566
 
4103
4567
  // src/components/ui/table/components/Table/parseTableChildren.ts
4104
- var import_react11 = require("react");
4568
+ var import_react12 = require("react");
4105
4569
 
4106
4570
  // src/components/ui/table/components/Table/tableChildTypes.ts
4107
- var import_react10 = require("react");
4571
+ var import_react11 = require("react");
4108
4572
  var TABLE_HEADER_DISPLAY_NAME = "Table.Header";
4109
4573
  var TABLE_BODY_DISPLAY_NAME = "Table.Body";
4110
4574
  var TABLE_COLUMN_DISPLAY_NAME = "Table.Column";
@@ -4117,19 +4581,19 @@ function getComponentDisplayName(type) {
4117
4581
  return void 0;
4118
4582
  }
4119
4583
  function isTableHeaderElement(child) {
4120
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4584
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_HEADER_DISPLAY_NAME;
4121
4585
  }
4122
4586
  function isTableBodyElement(child) {
4123
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4587
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_BODY_DISPLAY_NAME;
4124
4588
  }
4125
4589
  function isTableColumnElement(child) {
4126
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4590
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_DISPLAY_NAME;
4127
4591
  }
4128
4592
  function isTableColumnGroupElement(child) {
4129
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4593
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_COLUMN_GROUP_DISPLAY_NAME;
4130
4594
  }
4131
4595
  function isTablePaginationElement(child) {
4132
- return (0, import_react10.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4596
+ return (0, import_react11.isValidElement)(child) && getComponentDisplayName(child.type) === TABLE_PAGINATION_DISPLAY_NAME;
4133
4597
  }
4134
4598
 
4135
4599
  // src/components/ui/table/components/Table/parseTableChildren.ts
@@ -4139,7 +4603,7 @@ function parseTableChildren(children) {
4139
4603
  body: null,
4140
4604
  pagination: null
4141
4605
  };
4142
- for (const child of import_react11.Children.toArray(children)) {
4606
+ for (const child of import_react12.Children.toArray(children)) {
4143
4607
  if (isTableHeaderElement(child)) {
4144
4608
  slots.header = child;
4145
4609
  continue;
@@ -4156,7 +4620,7 @@ function parseTableChildren(children) {
4156
4620
  }
4157
4621
  function walkColumnTreeNodes(children) {
4158
4622
  const result = [];
4159
- for (const child of import_react11.Children.toArray(children)) {
4623
+ for (const child of import_react12.Children.toArray(children)) {
4160
4624
  if (isTableColumnElement(child)) {
4161
4625
  result.push({
4162
4626
  type: "leaf",
@@ -4173,7 +4637,7 @@ function walkColumnTreeNodes(children) {
4173
4637
  });
4174
4638
  continue;
4175
4639
  }
4176
- if ((0, import_react11.isValidElement)(child)) {
4640
+ if ((0, import_react12.isValidElement)(child)) {
4177
4641
  const nested = child.props.children;
4178
4642
  if (nested != null) {
4179
4643
  result.push(...walkColumnTreeNodes(nested));
@@ -4299,12 +4763,12 @@ function TableRoot({
4299
4763
  filteredCount,
4300
4764
  ...dataTableProps
4301
4765
  }) {
4302
- const { header, pagination: paginationElement } = (0, import_react12.useMemo)(
4766
+ const { header, pagination: paginationElement } = (0, import_react13.useMemo)(
4303
4767
  () => parseTableChildren(children),
4304
4768
  [children]
4305
4769
  );
4306
- const [sort, setSort] = (0, import_react12.useState)(null);
4307
- const handleSort = (0, import_react12.useCallback)((field) => {
4770
+ const [sort, setSort] = (0, import_react13.useState)(null);
4771
+ const handleSort = (0, import_react13.useCallback)((field) => {
4308
4772
  setSort((previous) => {
4309
4773
  if (previous?.field !== field) {
4310
4774
  return { field, direction: "asc" };
@@ -4315,8 +4779,8 @@ function TableRoot({
4315
4779
  return null;
4316
4780
  });
4317
4781
  }, []);
4318
- const columnTree = (0, import_react12.useMemo)(() => extractColumnTree(header), [header]);
4319
- const columns = (0, import_react12.useMemo)(
4782
+ const columnTree = (0, import_react13.useMemo)(() => extractColumnTree(header), [header]);
4783
+ const columns = (0, import_react13.useMemo)(
4320
4784
  () => buildColumnDefsFromTree(columnTree, sort, handleSort),
4321
4785
  [columnTree, sort, handleSort]
4322
4786
  );
@@ -4324,7 +4788,7 @@ function TableRoot({
4324
4788
  const pageSize = paginationProps?.pageSize ?? 10;
4325
4789
  const page = paginationProps?.page ?? 1;
4326
4790
  const resolvedTotalCount = paginationProps?.totalCount ?? totalCount ?? data.length;
4327
- const tableData = (0, import_react12.useMemo)(() => {
4791
+ const tableData = (0, import_react13.useMemo)(() => {
4328
4792
  const sortedData = sortTableData(data, sort);
4329
4793
  if (!paginationProps) return sortedData;
4330
4794
  return paginateTableData(sortedData, page, pageSize);