Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 56 additions & 8 deletions src/hooks/use-data-grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,21 @@ function useDataGrid<TData>({
}
}

const newData: TData[] = new Array(currentData.length);

for (let i = 0; i < currentData.length; i++) {
// Determine the full range of indices to cover — including any rows
// that were just added by onRowsAdd and are in the table but may not
// yet be reflected in propsRef.current.data (stale closure timing).
const maxUpdateIndex =
rowUpdatesMap.size > 0
? Math.max(...Array.from(rowUpdatesMap.keys()))
: -1;
const dataLength = Math.max(currentData.length, maxUpdateIndex + 1);
Comment on lines +410 to +414

const newData: TData[] = new Array(dataLength);

for (let i = 0; i < dataLength; i++) {
const updates = rowUpdatesMap.get(i);
const existingRow = currentData[i];
// Fall back to the table's row data for rows not yet in currentData
const existingRow = currentData[i] ?? rows?.[i]?.original;

if (existingRow == null) continue;

Expand Down Expand Up @@ -718,13 +728,51 @@ function useDataGrid<TData>({
if (!clipboardText) return;
}

const pastedData = parseTsv(clipboardText, navigableColumnIds.length);
const rawPastedData = parseTsv(
clipboardText,
navigableColumnIds.length,
);

// When clipboard has exactly one cell and the user has multiple cells
// selected, fill the entire selection with that single value.
const selectionCells = currentState.selectionState.selectedCells;
const isSingleCellClipboard =
rawPastedData.length === 1 && (rawPastedData[0]?.length ?? 0) === 1;
Comment on lines +736 to +740

const startRowIndex = currentState.focusedCell.rowIndex;
const startColIndex = navigableColumnIds.indexOf(
let pastedData = rawPastedData;
let startRowIndex = currentState.focusedCell.rowIndex;
let startColIndex = navigableColumnIds.indexOf(
currentState.focusedCell.columnId,
);

if (isSingleCellClipboard && selectionCells.size > 1) {
const singleValue = rawPastedData[0]?.[0] ?? "";
let minRow = Infinity;
let maxRow = -Infinity;
let minColIdx = Infinity;
let maxColIdx = -Infinity;

for (const cellKey of selectionCells) {
const { rowIndex, columnId } = parseCellKey(cellKey);
const colIdx = navigableColumnIds.indexOf(columnId);
if (colIdx === -1) continue;
minRow = Math.min(minRow, rowIndex);
maxRow = Math.max(maxRow, rowIndex);
minColIdx = Math.min(minColIdx, colIdx);
maxColIdx = Math.max(maxColIdx, colIdx);
}

if (minRow !== Infinity) {
startRowIndex = minRow;
startColIndex = minColIdx;
const numRows = maxRow - minRow + 1;
const numCols = maxColIdx - minColIdx + 1;
pastedData = Array.from({ length: numRows }, () =>
Array.from({ length: numCols }, () => singleValue),
);
}
}

if (startColIndex === -1) return;

const rowCount = rows.length ?? propsRef.current.data.length;
Expand Down Expand Up @@ -855,7 +903,7 @@ function useDataGrid<TData>({
case "select": {
const options = cellOpts?.options ?? [];
if (!pastedValue) {
processedValue = "";
processedValue = null;
} else {
const matched = matchSelectOption(pastedValue, options);
if (matched) processedValue = matched;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/data-grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export function parseTsv(
return rows;
}

const lines = text.split("\n");
const lines = text.split("\n").map((l) => l.replace(/\r$/, ""));
let maxTabCount = 0;
for (const line of lines) {
const n = countTabs(line);
Expand Down
Loading