react-glide-table 2.2.1 → 2.3.1

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/core.cjs CHANGED
@@ -80,6 +80,7 @@ __export(core_exports, {
80
80
  previousSearchIndex: () => previousSearchIndex,
81
81
  resolveCellRenderer: () => resolveCellRenderer,
82
82
  resolveColumnFreezeSide: () => resolveColumnFreezeSide,
83
+ resolveColumnLayoutWidths: () => resolveColumnLayoutWidths,
83
84
  resolveDataTableLabels: () => resolveDataTableLabels,
84
85
  resolveDropEdge: () => resolveDropEdge,
85
86
  resolveHeaderFreezeOffset: () => resolveHeaderFreezeOffset,
@@ -133,7 +134,7 @@ var DEFAULT_TREE_QTY_FIELD = "qty";
133
134
  // src/core/useGlideTable.ts
134
135
  var import_react_table = require("@tanstack/react-table");
135
136
  var import_react_virtual = require("@tanstack/react-virtual");
136
- var import_react5 = require("react");
137
+ var import_react6 = require("react");
137
138
 
138
139
  // src/components/ui/table/constants.ts
139
140
  var DATA_TABLE_ROW_HEIGHT = 44;
@@ -525,8 +526,92 @@ function withCellUpdate(context, commitValue) {
525
526
  };
526
527
  }
527
528
 
529
+ // src/components/ui/table/features/cell-selection/pasteData.ts
530
+ function countLeadingEmptyCells(cells) {
531
+ let depth = 0;
532
+ while (depth < cells.length && cells[depth] === "") {
533
+ depth += 1;
534
+ }
535
+ return depth;
536
+ }
537
+ function looksLikeSubtreeIndentation(leadingEmptyCounts) {
538
+ if (leadingEmptyCounts.length === 0) return false;
539
+ const firstDepth = leadingEmptyCounts[0] ?? 0;
540
+ if (firstDepth !== 0) return false;
541
+ return leadingEmptyCounts.some((depth) => depth > 0);
542
+ }
543
+ function parseClipboardTSV(text) {
544
+ return parseClipboardTSVWithDepths(text).values;
545
+ }
546
+ function parseClipboardTSVWithDepths(text) {
547
+ if (!text) return { values: [], depths: [] };
548
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
549
+ const withoutTrailing = normalized.replace(/\n+$/, "");
550
+ if (!withoutTrailing) return { values: [], depths: [] };
551
+ const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
552
+ const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
553
+ const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
554
+ const values = [];
555
+ const depths = [];
556
+ for (let index = 0; index < rows.length; index += 1) {
557
+ const cells = rows[index] ?? [];
558
+ const depth = leadingEmptyCounts[index] ?? 0;
559
+ if (treatAsDepth) {
560
+ values.push(cells.slice(depth));
561
+ depths.push(depth);
562
+ } else {
563
+ values.push(cells);
564
+ depths.push(0);
565
+ }
566
+ }
567
+ return { values, depths };
568
+ }
569
+ function resolvePasteColumnIds(rows, startCol, width) {
570
+ if (width <= 0) return [];
571
+ const cells = rows[0]?.getVisibleCells() ?? [];
572
+ const columnIds = [];
573
+ for (let offset = 0; offset < width; offset += 1) {
574
+ const cell = cells[startCol + offset];
575
+ if (!cell) break;
576
+ columnIds.push(cell.column.id);
577
+ }
578
+ return columnIds;
579
+ }
580
+ function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
581
+ const { values, depths } = parseClipboardTSVWithDepths(text);
582
+ if (values.length === 0) return null;
583
+ const width = Math.max(...values.map((row) => row.length), 0);
584
+ if (width === 0) return null;
585
+ const columnIds = resolvePasteColumnIds(rows, startCol, width);
586
+ if (columnIds.length === 0) return null;
587
+ const rowIds = [];
588
+ for (let offset = 0; offset < values.length; offset += 1) {
589
+ const row = rows[startRow + offset];
590
+ if (!row) break;
591
+ rowIds.push(row.id);
592
+ }
593
+ const anchorRow = rows[endRow] ?? rows[startRow];
594
+ return {
595
+ mode,
596
+ startRow,
597
+ startCol,
598
+ endRow,
599
+ rowIds,
600
+ anchorRowId: anchorRow?.id ?? "",
601
+ columnIds,
602
+ values,
603
+ depths
604
+ };
605
+ }
606
+ function isEditablePasteTarget(target) {
607
+ if (!(target instanceof HTMLElement)) return false;
608
+ const tag = target.tagName;
609
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
610
+ return Boolean(target.isContentEditable);
611
+ }
612
+
528
613
  // src/components/ui/table/features/cell-selection/useCellSelection.ts
529
- var import_react2 = require("react");
614
+ var import_react3 = require("react");
530
615
 
531
616
  // src/components/ui/table/features/cell-selection/cellSelection.ts
532
617
  var INITIAL_DRAG_STATE = {
@@ -834,6 +919,219 @@ function hasCellSelectionEdges(style) {
834
919
  }
835
920
 
836
921
  // src/components/ui/table/features/cell-selection/copyData.ts
922
+ var import_react2 = require("react");
923
+ function isReactNodeIterable(node) {
924
+ return typeof node === "object" && node !== null && !(0, import_react2.isValidElement)(node) && Symbol.iterator in node;
925
+ }
926
+ function getElementTypeName(type) {
927
+ if (typeof type === "string") return type;
928
+ if (typeof type === "function") {
929
+ const fn = type;
930
+ return fn.displayName || fn.name || "";
931
+ }
932
+ if (typeof type === "object" && type !== null) {
933
+ const component = type;
934
+ return component.displayName || component.render?.displayName || component.render?.name || "";
935
+ }
936
+ return "";
937
+ }
938
+ function isButtonReactElement(node) {
939
+ const typeName = getElementTypeName(node.type);
940
+ if (typeName === "button" || /button/i.test(typeName)) return true;
941
+ const props = node.props;
942
+ if (props.role === "button") return true;
943
+ if (typeName === "input" && props.type === "button") return true;
944
+ return false;
945
+ }
946
+ function isImageReactElement(node) {
947
+ const typeName = getElementTypeName(node.type);
948
+ return typeName === "img" || typeName === "image" || /image/i.test(typeName);
949
+ }
950
+ var IMAGE_URL_PROP_KEYS = ["src", "url", "href", "imageUrl", "srcUrl"];
951
+ function isLikelyUrl(value) {
952
+ const trimmed = value.trim();
953
+ if (!trimmed) return false;
954
+ if (/^(https?:|blob:|data:|\/\/)/i.test(trimmed)) return true;
955
+ if (trimmed.startsWith("/") && trimmed.includes("/")) return true;
956
+ return false;
957
+ }
958
+ function pickUrlFromUnknown(value) {
959
+ if (typeof value === "string") {
960
+ return isLikelyUrl(value) ? value.trim() : "";
961
+ }
962
+ if (Array.isArray(value)) {
963
+ return value.map((item) => pickUrlFromUnknown(item)).filter((item) => item.length > 0).join(", ");
964
+ }
965
+ if (value && typeof value === "object") {
966
+ const record = value;
967
+ for (const key of IMAGE_URL_PROP_KEYS) {
968
+ const candidate = record[key];
969
+ if (typeof candidate === "string" && candidate.trim()) {
970
+ return candidate.trim();
971
+ }
972
+ }
973
+ }
974
+ return "";
975
+ }
976
+ function imageElementText(node) {
977
+ const props = node.props;
978
+ for (const key of IMAGE_URL_PROP_KEYS) {
979
+ const candidate = props[key];
980
+ if (typeof candidate === "string" && candidate.trim()) {
981
+ return candidate.trim();
982
+ }
983
+ }
984
+ return "";
985
+ }
986
+ function reactNodeContainsImage(node) {
987
+ if ((0, import_react2.isValidElement)(node)) {
988
+ if (isImageReactElement(node)) return true;
989
+ return reactNodeContainsImage(node.props.children);
990
+ }
991
+ if (isReactNodeIterable(node)) {
992
+ for (const child of node) {
993
+ if (reactNodeContainsImage(child)) return true;
994
+ }
995
+ }
996
+ return false;
997
+ }
998
+ function readImgUrl(img) {
999
+ const attr = img.getAttribute("src")?.trim() ?? "";
1000
+ if (attr) return attr;
1001
+ if (img instanceof HTMLImageElement) {
1002
+ const current = img.currentSrc?.trim() ?? "";
1003
+ if (current && current !== img.baseURI) return current;
1004
+ }
1005
+ return "";
1006
+ }
1007
+ function readDomImageUrls(rowIndex, colIndex, root) {
1008
+ const scope = root ?? (typeof document === "undefined" ? null : document);
1009
+ if (!scope) return "";
1010
+ const cells = scope.querySelectorAll(
1011
+ `[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`
1012
+ );
1013
+ for (const cell of cells) {
1014
+ const urls = Array.from(cell.querySelectorAll("img")).flatMap((img) => {
1015
+ const url = readImgUrl(img);
1016
+ return url ? [url] : [];
1017
+ });
1018
+ if (urls.length > 0) return urls.join(", ");
1019
+ }
1020
+ return "";
1021
+ }
1022
+ function reactNodeToText(node) {
1023
+ if (node == null || typeof node === "boolean") return "";
1024
+ if (typeof node === "string" || typeof node === "number" || typeof node === "bigint") {
1025
+ return String(node);
1026
+ }
1027
+ if (isReactNodeIterable(node)) {
1028
+ let text = "";
1029
+ for (const child of node) {
1030
+ text += reactNodeToText(child);
1031
+ }
1032
+ return text;
1033
+ }
1034
+ if ((0, import_react2.isValidElement)(node)) {
1035
+ if (isButtonReactElement(node)) return "";
1036
+ const props = node.props;
1037
+ const childText = reactNodeToText(props.children);
1038
+ if (childText) return childText;
1039
+ const fromImage = imageElementText(node);
1040
+ if (fromImage) return fromImage;
1041
+ if (isImageReactElement(node)) return "";
1042
+ if (typeof props.alt === "string" && props.alt) return props.alt;
1043
+ if (typeof props.title === "string" && props.title) return props.title;
1044
+ return "";
1045
+ }
1046
+ return "";
1047
+ }
1048
+ function sanitizeClipboardCell(text) {
1049
+ return text.replace(/\s+/g, " ").trim();
1050
+ }
1051
+ function createCopyRenderRow(rowData, index) {
1052
+ return {
1053
+ id: getOriginalRowId(rowData) || String(index),
1054
+ index,
1055
+ original: rowData,
1056
+ getIsCellDragSelected: () => false
1057
+ };
1058
+ }
1059
+ function buildVisibleRowLookup(visibleRows) {
1060
+ const lookup = /* @__PURE__ */ new Map();
1061
+ for (const row of visibleRows) {
1062
+ lookup.set(row.original, row);
1063
+ }
1064
+ return lookup;
1065
+ }
1066
+ function resolveCopyColumnId(cell) {
1067
+ if (cell.column.id) return cell.column.id;
1068
+ const columnDef = cell.column.columnDef;
1069
+ if (columnDef.id) return columnDef.id;
1070
+ if (columnDef.accessorKey != null && columnDef.accessorKey !== "") {
1071
+ return String(columnDef.accessorKey);
1072
+ }
1073
+ return "";
1074
+ }
1075
+ function isPrimitiveCopyValue(value) {
1076
+ return value == null || typeof value !== "object";
1077
+ }
1078
+ function extractRenderedCopyText(node, value, cellPosition, root) {
1079
+ const rendered = sanitizeClipboardCell(reactNodeToText(node));
1080
+ if (reactNodeContainsImage(node)) {
1081
+ const fromDom = cellPosition != null ? sanitizeClipboardCell(
1082
+ readDomImageUrls(cellPosition.rowIndex, cellPosition.colIndex, root)
1083
+ ) : "";
1084
+ if (fromDom) return fromDom;
1085
+ if (rendered && isLikelyUrl(rendered)) return rendered;
1086
+ return sanitizeClipboardCell(pickUrlFromUnknown(value));
1087
+ }
1088
+ return rendered;
1089
+ }
1090
+ function formatCopyCellText(rowData, columnDef, columnId, visibleRow, fallbackIndex, sourceCell, cellPosition, options) {
1091
+ const meta = columnDef.meta;
1092
+ const value = sourceCell ? sourceCell.getValue() : readRowColumnValue(rowData, columnDef);
1093
+ const cellRender = meta?.cellRender;
1094
+ if (typeof cellRender === "function") {
1095
+ try {
1096
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
1097
+ const node = cellRender({
1098
+ value,
1099
+ row,
1100
+ index: row.index,
1101
+ columnId,
1102
+ cellProps: meta?.cellProps,
1103
+ update: () => {
1104
+ }
1105
+ });
1106
+ return extractRenderedCopyText(node, value, cellPosition, options?.root);
1107
+ } catch {
1108
+ return formatCellValue(value);
1109
+ }
1110
+ }
1111
+ if (options?.registry && meta?.kind && isPrimitiveCopyValue(value)) {
1112
+ try {
1113
+ const row = visibleRow ?? createCopyRenderRow(rowData, fallbackIndex);
1114
+ const ctx = {
1115
+ value,
1116
+ row,
1117
+ index: row.index,
1118
+ columnId,
1119
+ cellProps: meta.cellProps,
1120
+ update: () => {
1121
+ }
1122
+ };
1123
+ const renderer = resolveCellRenderer(options.registry, meta.kind, ctx);
1124
+ if (renderer) {
1125
+ const node = renderer.render(ctx);
1126
+ const rendered = extractRenderedCopyText(node, value, cellPosition, options.root);
1127
+ if (rendered) return rendered;
1128
+ }
1129
+ } catch {
1130
+ return formatCellValue(value);
1131
+ }
1132
+ }
1133
+ return formatCellValue(value);
1134
+ }
837
1135
  function formatPrimitive(value) {
838
1136
  if (value === null || value === void 0) return "";
839
1137
  if (typeof value === "string") return value;
@@ -939,37 +1237,47 @@ function collectCopyRowEntries(visibleRows, bounds, mode = "visible") {
939
1237
  function collectCopyRows(visibleRows, bounds, mode = "visible") {
940
1238
  return collectCopyRowEntries(visibleRows, bounds, mode).map((entry) => entry.row);
941
1239
  }
942
- function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths) {
1240
+ function serializeCopyRowsToTSV(copyRows, visibleRows, bounds, depths, options) {
943
1241
  if (copyRows.length === 0) return "";
944
1242
  const { startCol, endCol } = bounds;
945
1243
  const columnCells = visibleRows[0]?.getVisibleCells().slice(startCol, endCol + 1) ?? [];
946
1244
  if (columnCells.length === 0) return "";
947
1245
  const resolvedDepths = depths && depths.length === copyRows.length ? depths : copyRows.map((row) => getRowDepth(row));
948
1246
  const minDepth = Math.min(...resolvedDepths);
1247
+ const visibleRowByOriginal = buildVisibleRowLookup(visibleRows);
949
1248
  return copyRows.map((rowData, index) => {
950
1249
  const relativeDepth = Math.max(0, (resolvedDepths[index] ?? 0) - minDepth);
951
- const line = columnCells.map(
952
- (cell) => formatCellValue(
953
- readRowColumnValue(
954
- rowData,
955
- cell.column.columnDef
956
- )
957
- )
958
- ).join(" ");
1250
+ const visibleRow = visibleRowByOriginal.get(rowData);
1251
+ const matchingCells = visibleRow?.getVisibleCells().slice(startCol, endCol + 1);
1252
+ const line = columnCells.map((templateCell, colOffset) => {
1253
+ const sourceCell = matchingCells?.[colOffset];
1254
+ const column = sourceCell?.column ?? templateCell.column;
1255
+ return formatCopyCellText(
1256
+ rowData,
1257
+ column.columnDef,
1258
+ resolveCopyColumnId(sourceCell ?? templateCell),
1259
+ visibleRow,
1260
+ visibleRow?.index ?? index,
1261
+ sourceCell,
1262
+ visibleRow != null ? { rowIndex: visibleRow.index, colIndex: startCol + colOffset } : void 0,
1263
+ options
1264
+ );
1265
+ }).join(" ");
959
1266
  return `${" ".repeat(relativeDepth)}${line}`;
960
1267
  }).join("\n");
961
1268
  }
962
- function serializeSelectionToTSV(visibleRows, bounds, mode = "visible") {
1269
+ function serializeSelectionToTSV(visibleRows, bounds, mode = "visible", options) {
963
1270
  const entries = collectCopyRowEntries(visibleRows, bounds, mode);
964
1271
  return serializeCopyRowsToTSV(
965
1272
  entries.map((entry) => entry.row),
966
1273
  visibleRows,
967
1274
  bounds,
968
- entries.map((entry) => entry.depth)
1275
+ entries.map((entry) => entry.depth),
1276
+ options
969
1277
  );
970
1278
  }
971
- async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible") {
972
- const text = serializeSelectionToTSV(visibleRows, bounds, mode);
1279
+ async function writeSelectionToClipboard(visibleRows, bounds, mode = "visible", options) {
1280
+ const text = serializeSelectionToTSV(visibleRows, bounds, mode, options);
973
1281
  if (!text) return false;
974
1282
  try {
975
1283
  await navigator.clipboard.writeText(text);
@@ -1035,90 +1343,6 @@ function hasFillExtension(sourceBounds, fillBounds) {
1035
1343
  return fillBounds.startRow < sourceBounds.startRow || fillBounds.endRow > sourceBounds.endRow || fillBounds.startCol < sourceBounds.startCol || fillBounds.endCol > sourceBounds.endCol;
1036
1344
  }
1037
1345
 
1038
- // src/components/ui/table/features/cell-selection/pasteData.ts
1039
- function countLeadingEmptyCells(cells) {
1040
- let depth = 0;
1041
- while (depth < cells.length && cells[depth] === "") {
1042
- depth += 1;
1043
- }
1044
- return depth;
1045
- }
1046
- function looksLikeSubtreeIndentation(leadingEmptyCounts) {
1047
- if (leadingEmptyCounts.length === 0) return false;
1048
- const firstDepth = leadingEmptyCounts[0] ?? 0;
1049
- if (firstDepth !== 0) return false;
1050
- return leadingEmptyCounts.some((depth) => depth > 0);
1051
- }
1052
- function parseClipboardTSV(text) {
1053
- return parseClipboardTSVWithDepths(text).values;
1054
- }
1055
- function parseClipboardTSVWithDepths(text) {
1056
- if (!text) return { values: [], depths: [] };
1057
- const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1058
- const withoutTrailing = normalized.replace(/\n+$/, "");
1059
- if (!withoutTrailing) return { values: [], depths: [] };
1060
- const rows = withoutTrailing.split("\n").map((line) => line.split(" "));
1061
- const leadingEmptyCounts = rows.map(countLeadingEmptyCells);
1062
- const treatAsDepth = looksLikeSubtreeIndentation(leadingEmptyCounts);
1063
- const values = [];
1064
- const depths = [];
1065
- for (let index = 0; index < rows.length; index += 1) {
1066
- const cells = rows[index] ?? [];
1067
- const depth = leadingEmptyCounts[index] ?? 0;
1068
- if (treatAsDepth) {
1069
- values.push(cells.slice(depth));
1070
- depths.push(depth);
1071
- } else {
1072
- values.push(cells);
1073
- depths.push(0);
1074
- }
1075
- }
1076
- return { values, depths };
1077
- }
1078
- function resolvePasteColumnIds(rows, startCol, width) {
1079
- if (width <= 0) return [];
1080
- const cells = rows[0]?.getVisibleCells() ?? [];
1081
- const columnIds = [];
1082
- for (let offset = 0; offset < width; offset += 1) {
1083
- const cell = cells[startCol + offset];
1084
- if (!cell) break;
1085
- columnIds.push(cell.column.id);
1086
- }
1087
- return columnIds;
1088
- }
1089
- function buildRowsPastePayload(rows, startRow, startCol, text, mode, endRow = startRow) {
1090
- const { values, depths } = parseClipboardTSVWithDepths(text);
1091
- if (values.length === 0) return null;
1092
- const width = Math.max(...values.map((row) => row.length), 0);
1093
- if (width === 0) return null;
1094
- const columnIds = resolvePasteColumnIds(rows, startCol, width);
1095
- if (columnIds.length === 0) return null;
1096
- const rowIds = [];
1097
- for (let offset = 0; offset < values.length; offset += 1) {
1098
- const row = rows[startRow + offset];
1099
- if (!row) break;
1100
- rowIds.push(row.id);
1101
- }
1102
- const anchorRow = rows[endRow] ?? rows[startRow];
1103
- return {
1104
- mode,
1105
- startRow,
1106
- startCol,
1107
- endRow,
1108
- rowIds,
1109
- anchorRowId: anchorRow?.id ?? "",
1110
- columnIds,
1111
- values,
1112
- depths
1113
- };
1114
- }
1115
- function isEditablePasteTarget(target) {
1116
- if (!(target instanceof HTMLElement)) return false;
1117
- const tag = target.tagName;
1118
- if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
1119
- return Boolean(target.isContentEditable);
1120
- }
1121
-
1122
1346
  // src/components/ui/table/features/cell-selection/useCellSelection.ts
1123
1347
  function useCellSelection({
1124
1348
  data,
@@ -1130,17 +1354,19 @@ function useCellSelection({
1130
1354
  onDataChange,
1131
1355
  onBatchChange,
1132
1356
  onRowsPaste,
1133
- onCellNavigate
1357
+ onCellNavigate,
1358
+ cellRendererRegistry,
1359
+ rootRef
1134
1360
  }) {
1135
- const [dragState, setDragState] = (0, import_react2.useState)(INITIAL_DRAG_STATE);
1136
- const pendingPasteModeRef = (0, import_react2.useRef)(null);
1137
- const dragStateRef = (0, import_react2.useRef)(dragState);
1138
- const onCellNavigateRef = (0, import_react2.useRef)(onCellNavigate);
1361
+ const [dragState, setDragState] = (0, import_react3.useState)(INITIAL_DRAG_STATE);
1362
+ const pendingPasteModeRef = (0, import_react3.useRef)(null);
1363
+ const dragStateRef = (0, import_react3.useRef)(dragState);
1364
+ const onCellNavigateRef = (0, import_react3.useRef)(onCellNavigate);
1139
1365
  dragStateRef.current = dragState;
1140
1366
  onCellNavigateRef.current = onCellNavigate;
1141
1367
  const cellSelectionBounds = getCellSelectionBounds(dragState.start, dragState.end);
1142
1368
  const activeSelectionBounds = enabled ? getActiveSelectionBounds(dragState, cellSelectionBounds) : null;
1143
- const handleCellMouseDown = (0, import_react2.useCallback)(
1369
+ const handleCellMouseDown = (0, import_react3.useCallback)(
1144
1370
  (rowIndex, colIndex, options) => {
1145
1371
  if (!enabled) return;
1146
1372
  setDragState((prev) => {
@@ -1166,7 +1392,7 @@ function useCellSelection({
1166
1392
  },
1167
1393
  [enabled]
1168
1394
  );
1169
- const handleCellMouseEnter = (0, import_react2.useCallback)(
1395
+ const handleCellMouseEnter = (0, import_react3.useCallback)(
1170
1396
  (rowIndex, colIndex) => {
1171
1397
  if (!enabled) return;
1172
1398
  setDragState((prev) => {
@@ -1181,7 +1407,7 @@ function useCellSelection({
1181
1407
  },
1182
1408
  [enabled]
1183
1409
  );
1184
- const handleFillHandleMouseDown = (0, import_react2.useCallback)(
1410
+ const handleFillHandleMouseDown = (0, import_react3.useCallback)(
1185
1411
  (rowIndex, colIndex) => {
1186
1412
  if (!enabled) return;
1187
1413
  setDragState((prev) => {
@@ -1198,12 +1424,20 @@ function useCellSelection({
1198
1424
  },
1199
1425
  [enabled]
1200
1426
  );
1201
- (0, import_react2.useEffect)(() => {
1427
+ const clearSelection = (0, import_react3.useCallback)(() => {
1428
+ const prev = dragStateRef.current;
1429
+ if (prev.start === null && prev.end === null && !prev.isSelecting && !prev.isFillDragging) {
1430
+ return;
1431
+ }
1432
+ dragStateRef.current = INITIAL_DRAG_STATE;
1433
+ setDragState(INITIAL_DRAG_STATE);
1434
+ }, []);
1435
+ (0, import_react3.useEffect)(() => {
1202
1436
  if (!enabled) {
1203
- setDragState(INITIAL_DRAG_STATE);
1437
+ clearSelection();
1204
1438
  }
1205
- }, [enabled]);
1206
- (0, import_react2.useEffect)(() => {
1439
+ }, [clearSelection, enabled]);
1440
+ (0, import_react3.useEffect)(() => {
1207
1441
  if (!enabled) return;
1208
1442
  const handleKeyDown = (e) => {
1209
1443
  if (e.ctrlKey || e.metaKey || e.altKey) return;
@@ -1250,19 +1484,32 @@ function useCellSelection({
1250
1484
  window.addEventListener("keydown", handleKeyDown);
1251
1485
  return () => window.removeEventListener("keydown", handleKeyDown);
1252
1486
  }, [columnCount, enabled, rows]);
1253
- const copySelection = (0, import_react2.useCallback)(
1487
+ const copySelection = (0, import_react3.useCallback)(
1254
1488
  async (options) => {
1255
1489
  if (!enabled || !activeSelectionBounds) return false;
1256
1490
  const mode = options?.includeDescendants && enableSubtreeCopy ? "subtree" : "visible";
1257
- return writeSelectionToClipboard(rows, activeSelectionBounds, mode);
1491
+ return writeSelectionToClipboard(rows, activeSelectionBounds, mode, {
1492
+ registry: cellRendererRegistry,
1493
+ root: rootRef?.current
1494
+ });
1258
1495
  },
1259
- [activeSelectionBounds, enableSubtreeCopy, enabled, rows]
1496
+ [
1497
+ activeSelectionBounds,
1498
+ cellRendererRegistry,
1499
+ enableSubtreeCopy,
1500
+ enabled,
1501
+ rootRef,
1502
+ rows
1503
+ ]
1260
1504
  );
1261
- (0, import_react2.useEffect)(() => {
1505
+ (0, import_react3.useEffect)(() => {
1262
1506
  if (!enabled) return;
1263
1507
  const handleKeyDown = (e) => {
1264
1508
  if (!activeSelectionBounds) return;
1265
1509
  if (!(e.ctrlKey || e.metaKey)) return;
1510
+ if (isEditablePasteTarget(e.target) || isEditablePasteTarget(document.activeElement)) {
1511
+ return;
1512
+ }
1266
1513
  const isSubtreeShortcut = enableSubtreeCopy && e.shiftKey && e.key.toLowerCase() === "c";
1267
1514
  const isVisibleCopyShortcut = !e.shiftKey && e.key.toLowerCase() === "c";
1268
1515
  if (!isSubtreeShortcut && !isVisibleCopyShortcut) return;
@@ -1272,7 +1519,7 @@ function useCellSelection({
1272
1519
  window.addEventListener("keydown", handleKeyDown);
1273
1520
  return () => window.removeEventListener("keydown", handleKeyDown);
1274
1521
  }, [activeSelectionBounds, copySelection, enableSubtreeCopy, enabled]);
1275
- const emitRowsPaste = (0, import_react2.useCallback)(
1522
+ const emitRowsPaste = (0, import_react3.useCallback)(
1276
1523
  (text, mode) => {
1277
1524
  if (!onRowsPaste || !activeSelectionBounds) return false;
1278
1525
  const payload = buildRowsPastePayload(
@@ -1289,7 +1536,7 @@ function useCellSelection({
1289
1536
  },
1290
1537
  [activeSelectionBounds, onRowsPaste, rows]
1291
1538
  );
1292
- (0, import_react2.useEffect)(() => {
1539
+ (0, import_react3.useEffect)(() => {
1293
1540
  if (!enabled || !onRowsPaste) return;
1294
1541
  const pasteHandledRef = { current: false };
1295
1542
  const ignoreNextPasteRef = { current: false };
@@ -1357,7 +1604,7 @@ function useCellSelection({
1357
1604
  enabled,
1358
1605
  onRowsPaste
1359
1606
  ]);
1360
- (0, import_react2.useEffect)(() => {
1607
+ (0, import_react3.useEffect)(() => {
1361
1608
  if (!enabled) return;
1362
1609
  const handleMouseUp = () => {
1363
1610
  setDragState((prev) => {
@@ -1403,6 +1650,7 @@ function useCellSelection({
1403
1650
  handleCellMouseDown,
1404
1651
  handleCellMouseEnter,
1405
1652
  handleFillHandleMouseDown,
1653
+ clearSelection,
1406
1654
  copySelection
1407
1655
  };
1408
1656
  }
@@ -1800,7 +2048,7 @@ function collectAncestorKeysToExpand(corpusRow, expandedRows) {
1800
2048
  }
1801
2049
 
1802
2050
  // src/components/ui/table/features/inline-search/useInlineSearch.ts
1803
- var import_react3 = require("react");
2051
+ var import_react4 = require("react");
1804
2052
  var EMPTY_MATCH_KEYS = /* @__PURE__ */ new Set();
1805
2053
  function useInlineSearch({
1806
2054
  enabled = false,
@@ -1817,46 +2065,46 @@ function useInlineSearch({
1817
2065
  onNavigateToResult,
1818
2066
  rootRef
1819
2067
  }) {
1820
- const searchInputId = (0, import_react3.useId)();
1821
- const searchInputRef = (0, import_react3.useRef)(null);
1822
- const [internalShowSearch, setInternalShowSearch] = (0, import_react3.useState)(false);
1823
- const [internalSearchValue, setInternalSearchValue] = (0, import_react3.useState)("");
1824
- const [internalResults, setInternalResults] = (0, import_react3.useState)(
2068
+ const searchInputId = (0, import_react4.useId)();
2069
+ const searchInputRef = (0, import_react4.useRef)(null);
2070
+ const [internalShowSearch, setInternalShowSearch] = (0, import_react4.useState)(false);
2071
+ const [internalSearchValue, setInternalSearchValue] = (0, import_react4.useState)("");
2072
+ const [internalResults, setInternalResults] = (0, import_react4.useState)(
1825
2073
  []
1826
2074
  );
1827
- const [searchStatus, setSearchStatus] = (0, import_react3.useState)();
1828
- const searchStatusRef = (0, import_react3.useRef)(searchStatus);
2075
+ const [searchStatus, setSearchStatus] = (0, import_react4.useState)();
2076
+ const searchStatusRef = (0, import_react4.useRef)(searchStatus);
1829
2077
  searchStatusRef.current = searchStatus;
1830
- const abortControllerRef = (0, import_react3.useRef)(null);
1831
- const searchHandleRef = (0, import_react3.useRef)(void 0);
1832
- const initialStartRowRef = (0, import_react3.useRef)(initialStartRow);
2078
+ const abortControllerRef = (0, import_react4.useRef)(null);
2079
+ const searchHandleRef = (0, import_react4.useRef)(void 0);
2080
+ const initialStartRowRef = (0, import_react4.useRef)(initialStartRow);
1833
2081
  initialStartRowRef.current = initialStartRow;
1834
- const getCellValueRef = (0, import_react3.useRef)(getCellValue);
2082
+ const getCellValueRef = (0, import_react4.useRef)(getCellValue);
1835
2083
  getCellValueRef.current = getCellValue;
1836
2084
  const showSearch = controlledShowSearch ?? internalShowSearch;
1837
2085
  const searchValue = controlledSearchValue ?? internalSearchValue;
1838
2086
  const searchResults = controlledSearchResults ?? internalResults;
1839
- const setSearchValue = (0, import_react3.useCallback)(
2087
+ const setSearchValue = (0, import_react4.useCallback)(
1840
2088
  (value) => {
1841
2089
  setInternalSearchValue(value);
1842
2090
  onSearchValueChange?.(value);
1843
2091
  },
1844
2092
  [onSearchValueChange]
1845
2093
  );
1846
- const cancelSearch = (0, import_react3.useCallback)(() => {
2094
+ const cancelSearch = (0, import_react4.useCallback)(() => {
1847
2095
  if (searchHandleRef.current !== void 0) {
1848
2096
  window.cancelAnimationFrame(searchHandleRef.current);
1849
2097
  searchHandleRef.current = void 0;
1850
2098
  }
1851
2099
  abortControllerRef.current?.abort();
1852
2100
  }, []);
1853
- const emitResultsChanged = (0, import_react3.useCallback)(
2101
+ const emitResultsChanged = (0, import_react4.useCallback)(
1854
2102
  (results, navIndex) => {
1855
2103
  onSearchResultsChanged?.(results, navIndex);
1856
2104
  },
1857
2105
  [onSearchResultsChanged]
1858
2106
  );
1859
- const navigateToIndex = (0, import_react3.useCallback)(
2107
+ const navigateToIndex = (0, import_react4.useCallback)(
1860
2108
  (results, navIndex) => {
1861
2109
  if (onSearchResultsChanged) return;
1862
2110
  if (navIndex < 0 || navIndex >= results.length) return;
@@ -1866,7 +2114,7 @@ function useInlineSearch({
1866
2114
  },
1867
2115
  [onNavigateToResult, onSearchResultsChanged]
1868
2116
  );
1869
- const beginSearch = (0, import_react3.useCallback)(
2117
+ const beginSearch = (0, import_react4.useCallback)(
1870
2118
  (query) => {
1871
2119
  if (controlledSearchResults !== void 0) return;
1872
2120
  const totalRows = rowCount;
@@ -1938,12 +2186,12 @@ function useInlineSearch({
1938
2186
  rowCount
1939
2187
  ]
1940
2188
  );
1941
- const openSearch = (0, import_react3.useCallback)(() => {
2189
+ const openSearch = (0, import_react4.useCallback)(() => {
1942
2190
  if (controlledShowSearch === void 0) {
1943
2191
  setInternalShowSearch(true);
1944
2192
  }
1945
2193
  }, [controlledShowSearch]);
1946
- const closeSearch = (0, import_react3.useCallback)(() => {
2194
+ const closeSearch = (0, import_react4.useCallback)(() => {
1947
2195
  if (controlledShowSearch === void 0) {
1948
2196
  setInternalShowSearch(false);
1949
2197
  }
@@ -1958,7 +2206,7 @@ function useInlineSearch({
1958
2206
  emitResultsChanged,
1959
2207
  onSearchClose
1960
2208
  ]);
1961
- const goToNext = (0, import_react3.useCallback)(() => {
2209
+ const goToNext = (0, import_react4.useCallback)(() => {
1962
2210
  if (!searchStatus || searchStatus.results === 0) return;
1963
2211
  const newIndex = nextSearchIndex(
1964
2212
  searchStatus.selectedIndex,
@@ -1968,7 +2216,7 @@ function useInlineSearch({
1968
2216
  emitResultsChanged(searchResults, newIndex);
1969
2217
  navigateToIndex(searchResults, newIndex);
1970
2218
  }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1971
- const goToPrevious = (0, import_react3.useCallback)(() => {
2219
+ const goToPrevious = (0, import_react4.useCallback)(() => {
1972
2220
  if (!searchStatus || searchStatus.results === 0) return;
1973
2221
  const newIndex = previousSearchIndex(
1974
2222
  searchStatus.selectedIndex,
@@ -1978,7 +2226,7 @@ function useInlineSearch({
1978
2226
  emitResultsChanged(searchResults, newIndex);
1979
2227
  navigateToIndex(searchResults, newIndex);
1980
2228
  }, [emitResultsChanged, navigateToIndex, searchResults, searchStatus]);
1981
- (0, import_react3.useEffect)(() => {
2229
+ (0, import_react4.useEffect)(() => {
1982
2230
  if (controlledSearchResults === void 0) return;
1983
2231
  if (controlledSearchResults.length > 0) {
1984
2232
  setSearchStatus((current) => ({
@@ -1990,7 +2238,7 @@ function useInlineSearch({
1990
2238
  setSearchStatus(void 0);
1991
2239
  }
1992
2240
  }, [controlledSearchResults, rowCount]);
1993
- (0, import_react3.useEffect)(() => {
2241
+ (0, import_react4.useEffect)(() => {
1994
2242
  if (!enabled) return;
1995
2243
  setSearchStatus(void 0);
1996
2244
  setInternalResults([]);
@@ -2003,7 +2251,7 @@ function useInlineSearch({
2003
2251
  cancelSearch();
2004
2252
  }
2005
2253
  }, [enabled, showSearch]);
2006
- (0, import_react3.useEffect)(() => {
2254
+ (0, import_react4.useEffect)(() => {
2007
2255
  if (!enabled || !showSearch) return;
2008
2256
  if (controlledSearchResults !== void 0) return;
2009
2257
  if (searchValue.trim() === "") {
@@ -2023,7 +2271,7 @@ function useInlineSearch({
2023
2271
  searchValue,
2024
2272
  showSearch
2025
2273
  ]);
2026
- (0, import_react3.useEffect)(() => {
2274
+ (0, import_react4.useEffect)(() => {
2027
2275
  if (!enabled) return;
2028
2276
  const handleKeyDown = (event) => {
2029
2277
  if (!(event.ctrlKey || event.metaKey)) return;
@@ -2050,12 +2298,12 @@ function useInlineSearch({
2050
2298
  window.addEventListener("keydown", handleKeyDown, true);
2051
2299
  return () => window.removeEventListener("keydown", handleKeyDown, true);
2052
2300
  }, [controlledShowSearch, enabled, rootRef, showSearch]);
2053
- (0, import_react3.useEffect)(() => () => cancelSearch(), [cancelSearch]);
2054
- const searchMatchKeys = (0, import_react3.useMemo)(
2301
+ (0, import_react4.useEffect)(() => () => cancelSearch(), [cancelSearch]);
2302
+ const searchMatchKeys = (0, import_react4.useMemo)(
2055
2303
  () => buildSearchMatchKeys(searchResults),
2056
2304
  [searchResults]
2057
2305
  );
2058
- const activeMatch = (0, import_react3.useMemo)(() => {
2306
+ const activeMatch = (0, import_react4.useMemo)(() => {
2059
2307
  if (!searchStatus || searchStatus.selectedIndex < 0) return null;
2060
2308
  return searchResults[searchStatus.selectedIndex] ?? null;
2061
2309
  }, [searchResults, searchStatus]);
@@ -2098,7 +2346,7 @@ function useInlineSearch({
2098
2346
  }
2099
2347
 
2100
2348
  // src/components/ui/table/features/row-expand/row-expand.ts
2101
- var import_react4 = require("react");
2349
+ var import_react5 = require("react");
2102
2350
  function getFieldValue(row, key) {
2103
2351
  return row[key];
2104
2352
  }
@@ -2128,12 +2376,12 @@ var useConvertTreeData = ({
2128
2376
  expandedRows,
2129
2377
  onExpandedRowsChange
2130
2378
  }) => {
2131
- const onExpandedRowsChangeRef = (0, import_react4.useRef)(onExpandedRowsChange);
2132
- const hasInitializedRef = (0, import_react4.useRef)(false);
2133
- (0, import_react4.useEffect)(() => {
2379
+ const onExpandedRowsChangeRef = (0, import_react5.useRef)(onExpandedRowsChange);
2380
+ const hasInitializedRef = (0, import_react5.useRef)(false);
2381
+ (0, import_react5.useEffect)(() => {
2134
2382
  onExpandedRowsChangeRef.current = onExpandedRowsChange;
2135
2383
  }, [onExpandedRowsChange]);
2136
- (0, import_react4.useEffect)(() => {
2384
+ (0, import_react5.useEffect)(() => {
2137
2385
  if (!data || data.length === 0) {
2138
2386
  hasInitializedRef.current = false;
2139
2387
  return;
@@ -2143,7 +2391,7 @@ var useConvertTreeData = ({
2143
2391
  onExpandedRowsChangeRef.current?.(new Set(ids));
2144
2392
  hasInitializedRef.current = true;
2145
2393
  }, [enabled, data, toggleField]);
2146
- const processedData = (0, import_react4.useMemo)(() => {
2394
+ const processedData = (0, import_react5.useMemo)(() => {
2147
2395
  if (!enabled || !data || data.length === 0) return [];
2148
2396
  const flattenedData = [];
2149
2397
  const flattenItems = (items) => {
@@ -2207,7 +2455,7 @@ var useConvertTreeData = ({
2207
2455
  });
2208
2456
  return rootItems;
2209
2457
  }, [enabled, data, toggleField, childField, flattenField]);
2210
- const flattenTree = (0, import_react4.useMemo)(() => {
2458
+ const flattenTree = (0, import_react5.useMemo)(() => {
2211
2459
  if (!enabled) return [];
2212
2460
  const flatten = (nodes, result = [], level = 0) => {
2213
2461
  nodes.forEach((node, index) => {
@@ -2257,7 +2505,7 @@ var useConvertTreeData = ({
2257
2505
  preventExpand,
2258
2506
  expandedRows
2259
2507
  ]);
2260
- const sortedData = (0, import_react4.useMemo)(() => {
2508
+ const sortedData = (0, import_react5.useMemo)(() => {
2261
2509
  if (!enabled) {
2262
2510
  return data ?? [];
2263
2511
  }
@@ -2484,7 +2732,7 @@ function useGlideTable(options) {
2484
2732
  searchResults,
2485
2733
  onSearchResultsChanged
2486
2734
  } = options;
2487
- const labels = (0, import_react5.useMemo)(() => {
2735
+ const labels = (0, import_react6.useMemo)(() => {
2488
2736
  const resolved = resolveDataTableLabels(labelsProp);
2489
2737
  return {
2490
2738
  ...resolved,
@@ -2495,17 +2743,21 @@ function useGlideTable(options) {
2495
2743
  }, [labelsProp, emptyText, loadingText, selectionLabel]);
2496
2744
  const enableExpand = Boolean(toggleField);
2497
2745
  const resolvedEnableSubtreeCopy = enableSubtreeCopy ?? enableExpand;
2498
- const [internalRowSelection, setInternalRowSelection] = (0, import_react5.useState)({});
2499
- const [internalColumnSizing, setInternalColumnSizing] = (0, import_react5.useState)({});
2500
- const [internalColumnOrder, setInternalColumnOrder] = (0, import_react5.useState)([]);
2501
- const [internalExpandedRows, setInternalExpandedRows] = (0, import_react5.useState)(
2746
+ const [internalRowSelection, setInternalRowSelection] = (0, import_react6.useState)({});
2747
+ const [internalColumnSizing, setInternalColumnSizing] = (0, import_react6.useState)({});
2748
+ const [internalColumnOrder, setInternalColumnOrder] = (0, import_react6.useState)([]);
2749
+ const [internalExpandedRows, setInternalExpandedRows] = (0, import_react6.useState)(
2502
2750
  () => /* @__PURE__ */ new Set()
2503
2751
  );
2504
- const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react5.useState)(null);
2505
- const scrollRef = (0, import_react5.useRef)(null);
2506
- const rootRef = (0, import_react5.useRef)(null);
2752
+ const [hoveredRowIndex, setHoveredRowIndex] = (0, import_react6.useState)(null);
2753
+ const scrollRef = (0, import_react6.useRef)(null);
2754
+ const rootRef = (0, import_react6.useRef)(null);
2755
+ const cellRendererRegistry = (0, import_react6.useMemo)(
2756
+ () => createCellRendererRegistry(cellRenderers),
2757
+ [cellRenderers]
2758
+ );
2507
2759
  const shouldVirtualize = enableVirtualization && !enableRowSpan;
2508
- (0, import_react5.useEffect)(() => {
2760
+ (0, import_react6.useEffect)(() => {
2509
2761
  if (enableVirtualization && enableRowSpan) {
2510
2762
  console.warn(
2511
2763
  "[useGlideTable] enableRowSpan is on; virtualization is disabled to preserve cell merges."
@@ -2519,11 +2771,11 @@ function useGlideTable(options) {
2519
2771
  );
2520
2772
  const columnSizing = controlledColumnSizing ?? internalColumnSizing;
2521
2773
  const columnOrder = controlledColumnOrder ?? internalColumnOrder;
2522
- const tableColumns = (0, import_react5.useMemo)(() => {
2774
+ const tableColumns = (0, import_react6.useMemo)(() => {
2523
2775
  if (!enableColumnReorder) return columns;
2524
2776
  return applyLeafColumnOrder(columns, columnOrder);
2525
2777
  }, [columnOrder, columns, enableColumnReorder]);
2526
- const setColumnOrder = (0, import_react5.useCallback)(
2778
+ const setColumnOrder = (0, import_react6.useCallback)(
2527
2779
  (next) => {
2528
2780
  if (onColumnOrderChange) {
2529
2781
  onColumnOrderChange(next);
@@ -2534,7 +2786,7 @@ function useGlideTable(options) {
2534
2786
  [onColumnOrderChange]
2535
2787
  );
2536
2788
  const expandedRows = controlledExpandedRows ?? internalExpandedRows;
2537
- const handleExpandedRowsChange = (0, import_react5.useCallback)(
2789
+ const handleExpandedRowsChange = (0, import_react6.useCallback)(
2538
2790
  (next) => {
2539
2791
  if (onExpandedRowsChange) {
2540
2792
  onExpandedRowsChange(next);
@@ -2595,13 +2847,13 @@ function useGlideTable(options) {
2595
2847
  getCoreRowModel: (0, import_react_table.getCoreRowModel)(),
2596
2848
  getRowId: getRowId ? (originalRow, index) => getRowId(originalRow, index) : (_originalRow, index) => String(index)
2597
2849
  });
2598
- const rowSpanColumnKeys = (0, import_react5.useMemo)(() => {
2850
+ const rowSpanColumnKeys = (0, import_react6.useMemo)(() => {
2599
2851
  if (!enableRowSpan) return [];
2600
2852
  return collectRowSpanColumns(columns);
2601
2853
  }, [enableRowSpan, columns]);
2602
2854
  const primaryRowSpanKey = rowSpanColumnKeys[0]?.rowSpanKey;
2603
2855
  const primaryRowSpanColumnId = rowSpanColumnKeys[0]?.columnId;
2604
- const columnRowSpanMap = (0, import_react5.useMemo)(
2856
+ const columnRowSpanMap = (0, import_react6.useMemo)(
2605
2857
  () => buildColumnRowSpanMap(tableData, rowSpanColumnKeys),
2606
2858
  [tableData, rowSpanColumnKeys]
2607
2859
  );
@@ -2610,7 +2862,7 @@ function useGlideTable(options) {
2610
2862
  const rows = table.getRowModel().rows;
2611
2863
  const columnCount = table.getAllLeafColumns().length || 1;
2612
2864
  const visibleLeafColumns = table.getVisibleLeafColumns();
2613
- const columnFreezeOffsets = (0, import_react5.useMemo)(() => {
2865
+ const columnFreezeOffsets = (0, import_react6.useMemo)(() => {
2614
2866
  if (!enableColumnFreeze) return EMPTY_COLUMN_FREEZE_OFFSETS;
2615
2867
  return buildColumnFreezeOffsets(
2616
2868
  visibleLeafColumns.map((column) => ({
@@ -2630,14 +2882,14 @@ function useGlideTable(options) {
2630
2882
  const totalSize = rowVirtualizer.getTotalSize();
2631
2883
  const paddingTop = virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
2632
2884
  const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows[virtualRows.length - 1]?.end ?? 0) : 0;
2633
- const selectedRowIndices = (0, import_react5.useMemo)(() => {
2885
+ const selectedRowIndices = (0, import_react6.useMemo)(() => {
2634
2886
  const indices = /* @__PURE__ */ new Set();
2635
2887
  for (const selectedRow of selectedRows) {
2636
2888
  indices.add(selectedRow.index);
2637
2889
  }
2638
2890
  return indices;
2639
2891
  }, [selectedRows]);
2640
- const scrollCellIntoView = (0, import_react5.useCallback)(
2892
+ const scrollCellIntoView = (0, import_react6.useCallback)(
2641
2893
  (rowIndex, colIndex, options2) => {
2642
2894
  const align = options2?.align ?? "nearest";
2643
2895
  const blockAlign = align === "center" ? "center" : "nearest";
@@ -2664,7 +2916,7 @@ function useGlideTable(options) {
2664
2916
  },
2665
2917
  [rowVirtualizer, shouldVirtualize]
2666
2918
  );
2667
- const handleCellNavigate = (0, import_react5.useCallback)(
2919
+ const handleCellNavigate = (0, import_react6.useCallback)(
2668
2920
  (position) => {
2669
2921
  scrollCellIntoView(position.row, position.col, { align: "nearest" });
2670
2922
  },
@@ -2676,6 +2928,7 @@ function useGlideTable(options) {
2676
2928
  handleCellMouseDown,
2677
2929
  handleCellMouseEnter,
2678
2930
  handleFillHandleMouseDown,
2931
+ clearSelection: clearCellSelection,
2679
2932
  copySelection
2680
2933
  } = useCellSelection({
2681
2934
  data: tableData,
@@ -2687,8 +2940,46 @@ function useGlideTable(options) {
2687
2940
  onDataChange,
2688
2941
  onBatchChange,
2689
2942
  onRowsPaste,
2690
- onCellNavigate: handleCellNavigate
2943
+ onCellNavigate: handleCellNavigate,
2944
+ cellRendererRegistry,
2945
+ rootRef
2691
2946
  });
2947
+ const clearRowSelection = (0, import_react6.useCallback)(() => {
2948
+ if (rowSelectionMode === "none") return;
2949
+ const hasSelection = Object.values(rowSelection).some(Boolean);
2950
+ if (!hasSelection) return;
2951
+ if (onRowSelectionChange) {
2952
+ onRowSelectionChange(() => ({}));
2953
+ return;
2954
+ }
2955
+ setInternalRowSelection({});
2956
+ }, [onRowSelectionChange, rowSelection, rowSelectionMode]);
2957
+ (0, import_react6.useEffect)(() => {
2958
+ const clearAllSelections = () => {
2959
+ clearCellSelection();
2960
+ clearRowSelection();
2961
+ };
2962
+ const handleKeyDown = (event) => {
2963
+ if (event.key !== "Escape") return;
2964
+ if (event.defaultPrevented) return;
2965
+ if (isEditablePasteTarget(event.target) || isEditablePasteTarget(document.activeElement)) {
2966
+ return;
2967
+ }
2968
+ clearAllSelections();
2969
+ };
2970
+ const handleMouseDown = (event) => {
2971
+ const root = rootRef.current;
2972
+ if (!root) return;
2973
+ if (event.target instanceof Node && root.contains(event.target)) return;
2974
+ clearAllSelections();
2975
+ };
2976
+ window.addEventListener("keydown", handleKeyDown);
2977
+ document.addEventListener("mousedown", handleMouseDown);
2978
+ return () => {
2979
+ window.removeEventListener("keydown", handleKeyDown);
2980
+ document.removeEventListener("mousedown", handleMouseDown);
2981
+ };
2982
+ }, [clearCellSelection, clearRowSelection]);
2692
2983
  const {
2693
2984
  editingCell,
2694
2985
  draftValue,
@@ -2697,11 +2988,7 @@ function useGlideTable(options) {
2697
2988
  commitEdit,
2698
2989
  cancelEdit
2699
2990
  } = useCellEdit({ data: tableData, rows, onDataChange, onCellChange });
2700
- const cellRendererRegistry = (0, import_react5.useMemo)(
2701
- () => createCellRendererRegistry(cellRenderers),
2702
- [cellRenderers]
2703
- );
2704
- const commitRenderedCellValue = (0, import_react5.useCallback)(
2991
+ const commitRenderedCellValue = (0, import_react6.useCallback)(
2705
2992
  (rowId, columnId, value) => commitCellValue({
2706
2993
  data: tableData,
2707
2994
  rows,
@@ -2713,11 +3000,11 @@ function useGlideTable(options) {
2713
3000
  }),
2714
3001
  [onCellChange, onDataChange, rows, tableData]
2715
3002
  );
2716
- const getCellContext = (0, import_react5.useCallback)(
3003
+ const getCellContext = (0, import_react6.useCallback)(
2717
3004
  (cell) => withCellUpdate(cell.getContext(), commitRenderedCellValue),
2718
3005
  [commitRenderedCellValue]
2719
3006
  );
2720
- const handleCellMouseDownWithCommit = (0, import_react5.useCallback)(
3007
+ const handleCellMouseDownWithCommit = (0, import_react6.useCallback)(
2721
3008
  (rowIndex, colIndex, options2) => {
2722
3009
  const isSameEditingCell = editingCell?.rowIndex === rowIndex && editingCell?.colIndex === colIndex;
2723
3010
  if (editingCell && !isSameEditingCell && !commitEdit()) {
@@ -2727,7 +3014,7 @@ function useGlideTable(options) {
2727
3014
  },
2728
3015
  [commitEdit, editingCell, handleCellMouseDown]
2729
3016
  );
2730
- const navigateToSearchResult = (0, import_react5.useCallback)(
3017
+ const navigateToSearchResult = (0, import_react6.useCallback)(
2731
3018
  (item) => {
2732
3019
  const [colIndex, rowIndex] = item;
2733
3020
  handleCellMouseDownWithCommit(rowIndex, colIndex);
@@ -2735,7 +3022,7 @@ function useGlideTable(options) {
2735
3022
  },
2736
3023
  [handleCellMouseDownWithCommit, scrollCellIntoView]
2737
3024
  );
2738
- const resolveSearchRowId = (0, import_react5.useCallback)(
3025
+ const resolveSearchRowId = (0, import_react6.useCallback)(
2739
3026
  (row, index) => {
2740
3027
  if (getRowId) return getRowId(row, index);
2741
3028
  if (enableExpand) {
@@ -2759,7 +3046,7 @@ function useGlideTable(options) {
2759
3046
  },
2760
3047
  [enableExpand, getRowId, toggleField]
2761
3048
  );
2762
- const searchCorpus = (0, import_react5.useMemo)(() => {
3049
+ const searchCorpus = (0, import_react6.useMemo)(() => {
2763
3050
  if (!enableInlineSearch) return [];
2764
3051
  if (enableExpand && toggleField) {
2765
3052
  return buildTreeSearchCorpus(tableData, {
@@ -2775,16 +3062,16 @@ function useGlideTable(options) {
2775
3062
  tableData,
2776
3063
  toggleField
2777
3064
  ]);
2778
- const searchCorpusRef = (0, import_react5.useRef)(searchCorpus);
3065
+ const searchCorpusRef = (0, import_react6.useRef)(searchCorpus);
2779
3066
  searchCorpusRef.current = searchCorpus;
2780
- const visibleRowIndexById = (0, import_react5.useMemo)(() => {
3067
+ const visibleRowIndexById = (0, import_react6.useMemo)(() => {
2781
3068
  const map = /* @__PURE__ */ new Map();
2782
3069
  for (const row of rows) {
2783
3070
  map.set(resolveSearchRowId(row.original, row.index), row.index);
2784
3071
  }
2785
3072
  return map;
2786
3073
  }, [resolveSearchRowId, rows]);
2787
- const getSearchCellValue = (0, import_react5.useCallback)(
3074
+ const getSearchCellValue = (0, import_react6.useCallback)(
2788
3075
  (rowIndex, colIndex) => {
2789
3076
  const corpusRow = searchCorpusRef.current[rowIndex];
2790
3077
  const column = visibleLeafColumns[colIndex];
@@ -2807,14 +3094,14 @@ function useGlideTable(options) {
2807
3094
  },
2808
3095
  [rows, visibleLeafColumns, visibleRowIndexById]
2809
3096
  );
2810
- const pendingSearchNavRef = (0, import_react5.useRef)(null);
2811
- const focusSearchResult = (0, import_react5.useCallback)(
3097
+ const pendingSearchNavRef = (0, import_react6.useRef)(null);
3098
+ const focusSearchResult = (0, import_react6.useCallback)(
2812
3099
  (colIndex, visibleRowIndex) => {
2813
3100
  navigateToSearchResult([colIndex, visibleRowIndex]);
2814
3101
  },
2815
3102
  [navigateToSearchResult]
2816
3103
  );
2817
- const navigateToCorpusSearchResult = (0, import_react5.useCallback)(
3104
+ const navigateToCorpusSearchResult = (0, import_react6.useCallback)(
2818
3105
  (item) => {
2819
3106
  const [colIndex, corpusRowIndex] = item;
2820
3107
  const corpusRow = searchCorpusRef.current[corpusRowIndex];
@@ -2847,7 +3134,7 @@ function useGlideTable(options) {
2847
3134
  visibleRowIndexById
2848
3135
  ]
2849
3136
  );
2850
- (0, import_react5.useEffect)(() => {
3137
+ (0, import_react6.useEffect)(() => {
2851
3138
  const pending = pendingSearchNavRef.current;
2852
3139
  if (!pending) return;
2853
3140
  const visibleRowIndex = visibleRowIndexById.get(pending.rowId);
@@ -2871,7 +3158,7 @@ function useGlideTable(options) {
2871
3158
  onNavigateToResult: navigateToCorpusSearchResult,
2872
3159
  rootRef
2873
3160
  });
2874
- const visibleSearchMatchKeys = (0, import_react5.useMemo)(() => {
3161
+ const visibleSearchMatchKeys = (0, import_react6.useMemo)(() => {
2875
3162
  if (!enableInlineSearch) return EMPTY_SEARCH_MATCH_KEYS;
2876
3163
  return mapSearchResultsToVisibleKeys(
2877
3164
  inlineSearch.searchResults,
@@ -2884,7 +3171,7 @@ function useGlideTable(options) {
2884
3171
  searchCorpus,
2885
3172
  visibleRowIndexById
2886
3173
  ]);
2887
- const visibleActiveMatch = (0, import_react5.useMemo)(() => {
3174
+ const visibleActiveMatch = (0, import_react6.useMemo)(() => {
2888
3175
  if (!enableInlineSearch || !inlineSearch.activeMatch) return null;
2889
3176
  return mapSearchResultToVisibleItem(
2890
3177
  inlineSearch.activeMatch,
@@ -2897,13 +3184,13 @@ function useGlideTable(options) {
2897
3184
  searchCorpus,
2898
3185
  visibleRowIndexById
2899
3186
  ]);
2900
- const clearHover = (0, import_react5.useCallback)(() => {
3187
+ const clearHover = (0, import_react6.useCallback)(() => {
2901
3188
  setHoveredRowIndex(null);
2902
3189
  }, []);
2903
- const handleRowHover = (0, import_react5.useCallback)((rowIndex, _rowData) => {
3190
+ const handleRowHover = (0, import_react6.useCallback)((rowIndex, _rowData) => {
2904
3191
  setHoveredRowIndex(rowIndex);
2905
3192
  }, []);
2906
- const handleToggleSelect = (0, import_react5.useCallback)(
3193
+ const handleToggleSelect = (0, import_react6.useCallback)(
2907
3194
  (row) => {
2908
3195
  if (!row.getCanSelect()) return;
2909
3196
  if (preserveRowSelection && row.getIsSelected()) {
@@ -2913,14 +3200,14 @@ function useGlideTable(options) {
2913
3200
  },
2914
3201
  [preserveRowSelection]
2915
3202
  );
2916
- const handleToggleExpand = (0, import_react5.useCallback)(
3203
+ const handleToggleExpand = (0, import_react6.useCallback)(
2917
3204
  (rowKey) => {
2918
3205
  if (preventExpand) return;
2919
3206
  handleExpandedRowsChange(toggleExpandedRowId(rowKey, expandedRows));
2920
3207
  },
2921
3208
  [preventExpand, handleExpandedRowsChange, expandedRows]
2922
3209
  );
2923
- const rowContextValue = (0, import_react5.useMemo)(() => {
3210
+ const rowContextValue = (0, import_react6.useMemo)(() => {
2924
3211
  return {
2925
3212
  rowSpan: {
2926
3213
  enableRowSpan,
@@ -3019,12 +3306,12 @@ function useGlideTable(options) {
3019
3306
  visibleSearchMatchKeys,
3020
3307
  visibleActiveMatch
3021
3308
  ]);
3022
- const copySelectionRef = (0, import_react5.useRef)(copySelection);
3023
- (0, import_react5.useEffect)(() => {
3309
+ const copySelectionRef = (0, import_react6.useRef)(copySelection);
3310
+ (0, import_react6.useEffect)(() => {
3024
3311
  copySelectionRef.current = copySelection;
3025
3312
  }, [copySelection]);
3026
- const stableCopySelection = (0, import_react5.useCallback)((options2) => copySelectionRef.current(options2), []);
3027
- (0, import_react5.useEffect)(() => {
3313
+ const stableCopySelection = (0, import_react6.useCallback)((options2) => copySelectionRef.current(options2), []);
3314
+ (0, import_react6.useEffect)(() => {
3028
3315
  onCopyActionsReady?.({ copySelection: stableCopySelection });
3029
3316
  }, [onCopyActionsReady, stableCopySelection]);
3030
3317
  return {
@@ -3073,16 +3360,18 @@ function useGlideTable(options) {
3073
3360
  }
3074
3361
 
3075
3362
  // src/components/ui/table/features/cell-render/ResolvedTableCell.tsx
3076
- var import_react7 = require("react");
3363
+ var import_react8 = require("react");
3077
3364
 
3078
3365
  // src/components/ui/table/DataTableContext.tsx
3079
- var import_react6 = require("react");
3366
+ var import_react7 = require("react");
3080
3367
  var import_jsx_runtime2 = require("react/jsx-runtime");
3081
- var DataTableContext = (0, import_react6.createContext)(null);
3368
+ var DataTableContext = (0, import_react7.createContext)(null);
3082
3369
  function useDataTableRowContext() {
3083
- const context = (0, import_react6.use)(DataTableContext);
3370
+ const context = (0, import_react7.use)(DataTableContext);
3084
3371
  if (!context) {
3085
- throw new Error("useDataTableRowContext must be used within a DataTableContextProvider");
3372
+ throw new Error(
3373
+ "useDataTableRowContext must be used within a DataTableContextProvider"
3374
+ );
3086
3375
  }
3087
3376
  return context;
3088
3377
  }
@@ -3096,7 +3385,7 @@ function ResolvedTableCell({
3096
3385
  const meta = column.columnDef.meta;
3097
3386
  const value = getValue();
3098
3387
  const columnId = column.id;
3099
- const update = (0, import_react7.useCallback)(
3388
+ const update = (0, import_react8.useCallback)(
3100
3389
  (next) => {
3101
3390
  cellRender.commitValue(row.id, columnId, next);
3102
3391
  },
@@ -3121,8 +3410,105 @@ function ResolvedTableCell({
3121
3410
  }
3122
3411
 
3123
3412
  // src/components/ui/table/features/column-resize/columnResize.ts
3413
+ function clamp(value, min, max) {
3414
+ return Math.min(Math.max(value, min), max);
3415
+ }
3416
+ function floorOf(column) {
3417
+ return column.minWidth ?? 0;
3418
+ }
3419
+ function ceilOf(column) {
3420
+ return column.maxWidth ?? Number.POSITIVE_INFINITY;
3421
+ }
3422
+ function preferOf(column) {
3423
+ const floor = floorOf(column);
3424
+ const ceil = ceilOf(column);
3425
+ const preferred = column.maxWidth ?? column.minWidth ?? 0;
3426
+ return clamp(preferred, floor, Number.isFinite(ceil) ? ceil : preferred);
3427
+ }
3428
+ function resolveColumnLayoutWidths(containerWidth, columns) {
3429
+ const widths = /* @__PURE__ */ new Map();
3430
+ const fixed = [];
3431
+ const bounded = [];
3432
+ let flexCount = 0;
3433
+ for (const column of columns) {
3434
+ if (column.width != null) {
3435
+ fixed.push(column);
3436
+ } else if (column.minWidth != null || column.maxWidth != null) {
3437
+ bounded.push(column);
3438
+ } else {
3439
+ flexCount += 1;
3440
+ }
3441
+ }
3442
+ let used = 0;
3443
+ for (const column of fixed) {
3444
+ let size = column.width;
3445
+ if (column.minWidth != null) size = Math.max(size, column.minWidth);
3446
+ if (column.maxWidth != null) size = Math.min(size, column.maxWidth);
3447
+ widths.set(column.id, size);
3448
+ used += size;
3449
+ }
3450
+ if (bounded.length === 0) {
3451
+ return widths;
3452
+ }
3453
+ const boundedSizes = /* @__PURE__ */ new Map();
3454
+ let preferredSum = 0;
3455
+ let floorSum = 0;
3456
+ for (const column of bounded) {
3457
+ const preferred = preferOf(column);
3458
+ boundedSizes.set(column.id, preferred);
3459
+ preferredSum += preferred;
3460
+ floorSum += floorOf(column);
3461
+ }
3462
+ if (containerWidth > 0) {
3463
+ const remaining = Math.max(0, containerWidth - used);
3464
+ if (remaining >= preferredSum) {
3465
+ } else if (remaining >= floorSum) {
3466
+ let deficit = preferredSum - remaining;
3467
+ const open = bounded.map((column) => ({
3468
+ id: column.id,
3469
+ current: boundedSizes.get(column.id),
3470
+ floor: floorOf(column)
3471
+ }));
3472
+ while (deficit >= 1) {
3473
+ const shrinkable = open.filter((entry) => entry.current > entry.floor);
3474
+ if (shrinkable.length === 0) break;
3475
+ const portion = Math.floor(deficit / shrinkable.length);
3476
+ const rem = deficit % shrinkable.length;
3477
+ let consumed = 0;
3478
+ for (let index = 0; index < shrinkable.length; index += 1) {
3479
+ const entry = shrinkable[index];
3480
+ const reduce = Math.min(
3481
+ entry.current - entry.floor,
3482
+ portion + (index < rem ? 1 : 0)
3483
+ );
3484
+ entry.current -= reduce;
3485
+ consumed += reduce;
3486
+ }
3487
+ if (consumed === 0) break;
3488
+ deficit -= consumed;
3489
+ }
3490
+ for (const entry of open) {
3491
+ boundedSizes.set(entry.id, entry.current);
3492
+ }
3493
+ } else {
3494
+ for (const column of bounded) {
3495
+ boundedSizes.set(column.id, floorOf(column));
3496
+ }
3497
+ }
3498
+ }
3499
+ for (const [id, size] of boundedSizes) {
3500
+ widths.set(id, Math.round(size));
3501
+ }
3502
+ return widths;
3503
+ }
3124
3504
  function getColumnSizeStyle(size, options) {
3125
- const { force = false, lockMax = false, minWidth, maxWidth } = options ?? {};
3505
+ const {
3506
+ force = false,
3507
+ lockMax = false,
3508
+ minWidth,
3509
+ maxWidth,
3510
+ layoutWidth
3511
+ } = options ?? {};
3126
3512
  if (lockMax) {
3127
3513
  return {
3128
3514
  width: size,
@@ -3130,14 +3516,27 @@ function getColumnSizeStyle(size, options) {
3130
3516
  maxWidth: size
3131
3517
  };
3132
3518
  }
3519
+ if (layoutWidth != null) {
3520
+ return {
3521
+ width: layoutWidth,
3522
+ minWidth: layoutWidth,
3523
+ maxWidth: layoutWidth
3524
+ };
3525
+ }
3526
+ const resolvedSize = size;
3133
3527
  const hasExplicitSize = force || size !== DATA_TABLE_COLUMN_SIZE;
3134
3528
  if (!hasExplicitSize && minWidth == null && maxWidth == null) {
3135
3529
  return void 0;
3136
3530
  }
3137
3531
  const style = {};
3138
3532
  if (hasExplicitSize) {
3139
- style.width = size;
3140
- style.minWidth = minWidth ?? size;
3533
+ const used = minWidth != null || maxWidth != null ? clamp(
3534
+ resolvedSize,
3535
+ minWidth ?? Number.NEGATIVE_INFINITY,
3536
+ maxWidth ?? Number.POSITIVE_INFINITY
3537
+ ) : resolvedSize;
3538
+ style.width = used;
3539
+ style.minWidth = minWidth ?? used;
3141
3540
  } else if (minWidth != null) {
3142
3541
  style.minWidth = minWidth;
3143
3542
  }
@@ -3148,7 +3547,7 @@ function getColumnSizeStyle(size, options) {
3148
3547
  }
3149
3548
 
3150
3549
  // src/components/ui/table/features/column-reorder/useColumnReorder.ts
3151
- var import_react8 = require("react");
3550
+ var import_react9 = require("react");
3152
3551
  function hitTestReorderHeader(table, clientX, clientY) {
3153
3552
  const headers = Array.from(
3154
3553
  table.querySelectorAll(
@@ -3196,19 +3595,19 @@ function readTargetIds(table, columnId) {
3196
3595
  }
3197
3596
  function useColumnReorder(options) {
3198
3597
  const { enabled, columnOrder, onColumnOrderChange } = options;
3199
- const sessionRef = (0, import_react8.useRef)(null);
3200
- const columnOrderRef = (0, import_react8.useRef)(columnOrder);
3201
- const onColumnOrderChangeRef = (0, import_react8.useRef)(onColumnOrderChange);
3202
- const [draggingColumnId, setDraggingColumnId] = (0, import_react8.useState)(null);
3203
- const [dropTarget, setDropTarget] = (0, import_react8.useState)(
3598
+ const sessionRef = (0, import_react9.useRef)(null);
3599
+ const columnOrderRef = (0, import_react9.useRef)(columnOrder);
3600
+ const onColumnOrderChangeRef = (0, import_react9.useRef)(onColumnOrderChange);
3601
+ const [draggingColumnId, setDraggingColumnId] = (0, import_react9.useState)(null);
3602
+ const [dropTarget, setDropTarget] = (0, import_react9.useState)(
3204
3603
  null
3205
3604
  );
3206
- const dropTargetRef = (0, import_react8.useRef)(dropTarget);
3207
- const previousUserSelectRef = (0, import_react8.useRef)(null);
3605
+ const dropTargetRef = (0, import_react9.useRef)(dropTarget);
3606
+ const previousUserSelectRef = (0, import_react9.useRef)(null);
3208
3607
  columnOrderRef.current = columnOrder;
3209
3608
  onColumnOrderChangeRef.current = onColumnOrderChange;
3210
3609
  dropTargetRef.current = dropTarget;
3211
- const resetDrag = (0, import_react8.useCallback)(() => {
3610
+ const resetDrag = (0, import_react9.useCallback)(() => {
3212
3611
  sessionRef.current = null;
3213
3612
  setDraggingColumnId(null);
3214
3613
  setDropTarget(null);
@@ -3224,15 +3623,15 @@ function useColumnReorder(options) {
3224
3623
  }
3225
3624
  document.body.style.removeProperty("user-select");
3226
3625
  }, []);
3227
- (0, import_react8.useEffect)(() => {
3626
+ (0, import_react9.useEffect)(() => {
3228
3627
  if (!enabled) resetDrag();
3229
3628
  }, [enabled, resetDrag]);
3230
- (0, import_react8.useEffect)(() => {
3629
+ (0, import_react9.useEffect)(() => {
3231
3630
  return () => {
3232
3631
  resetDrag();
3233
3632
  };
3234
3633
  }, [resetDrag]);
3235
- const onHeaderPointerDown = (0, import_react8.useCallback)(
3634
+ const onHeaderPointerDown = (0, import_react9.useCallback)(
3236
3635
  (event, meta) => {
3237
3636
  if (!enabled || !meta.canDrag) return;
3238
3637
  if (event.button !== 0) return;
@@ -3255,7 +3654,7 @@ function useColumnReorder(options) {
3255
3654
  },
3256
3655
  [enabled]
3257
3656
  );
3258
- (0, import_react8.useEffect)(() => {
3657
+ (0, import_react9.useEffect)(() => {
3259
3658
  if (!enabled) return;
3260
3659
  const onPointerMove = (event) => {
3261
3660
  const session = sessionRef.current;
@@ -3416,6 +3815,7 @@ function useColumnReorder(options) {
3416
3815
  previousSearchIndex,
3417
3816
  resolveCellRenderer,
3418
3817
  resolveColumnFreezeSide,
3818
+ resolveColumnLayoutWidths,
3419
3819
  resolveDataTableLabels,
3420
3820
  resolveDropEdge,
3421
3821
  resolveHeaderFreezeOffset,