Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions public/r/data-grid.json

Large diffs are not rendered by default.

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);

const newData: TData[] = new Array(dataLength);
Comment thread
sadmann7 marked this conversation as resolved.

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;

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),
);
}
Comment thread
sadmann7 marked this conversation as resolved.
}

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 {
Comment thread
sadmann7 marked this conversation as resolved.
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$/, ""));
Comment thread
sadmann7 marked this conversation as resolved.
let maxTabCount = 0;
for (const line of lines) {
const n = countTabs(line);
Expand Down
Loading