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
9 changes: 8 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import './test/theming-test.scss';
import {
config, enablePinnedToBodyConfig, disabledInitialFocusLocationConfig, enableAdditionalContentConfig,
enableAdditionalContentWithFlexRowConfig, enableSymetric, enableTopLeftResponsiveSticky, enableTopLeftResponsiveStickyPinnedToBody,
enableBottomRightResponsiveSticky, enableBottomRightResponsiveStickyPinnedToBody, enableSpannedCells, disableVirtualScrolling
enableBottomRightResponsiveSticky, enableBottomRightResponsiveStickyPinnedToBody, enableSpannedCells, disableVirtualScrolling, allowExtendPasteRangeConfig
} from './test/testEnvConfig';

let component = <ExtTestGrid
Expand All @@ -15,6 +15,13 @@ let component = <ExtTestGrid
/>;
ExtTestGrid.displayName = 'TestGridPro';
switch (window.location.pathname) {
case '/allowExtendPasteRange':
component = <ExtTestGrid
component={ReactGrid}
config={allowExtendPasteRangeConfig}
/>;
ExtTestGrid.displayName = 'TestGridProWithAllowExtendPasteRange';
break;
case '/enableColumnAndRowSelection':
component = <ExtTestGrid
component={ReactGrid}
Expand Down
64 changes: 64 additions & 0 deletions src/lib/Functions/expandGridIfNeeded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { CellMatrix } from "../Model/CellMatrix";
import { State } from "../Model/State";

/**
* Expand the grid if needed
* @param state State object
* @param endRow End line
* @param endColumn End column number
* @returns Updated status object
*/
export const expandGridIfNeeded = (
state: State,
endRow: number,
endColumn: number
): State => {
const { cellMatrix } = state;
let updated = false;

// Determines the current number of rows and columns
const currentRowCount = cellMatrix.rows.length;
const currentColumnCount = cellMatrix.columns.length;

// Add new columns if needed
if (endColumn >= currentColumnCount) {
const columnsToAdd = endColumn - currentColumnCount + 1;
const prefix = cellMatrix.columns[currentColumnCount - 1];
for (let i = 0; i < columnsToAdd; i++) {
cellMatrix.columns.push({
...prefix,
columnId: currentColumnCount + i,
idx: currentColumnCount + i,
left: prefix.right,
right: prefix.right + prefix.width || CellMatrix.DEFAULT_COLUMN_WIDTH,
});
cellMatrix.rows.map((_row) => {
_row.cells.push({
type: "text",
text: "",
});
return _row;
});
}
updated = true;
}

// Add new rows if needed
if (endRow >= currentRowCount) {
const rowsToAdd = endRow - currentRowCount + 1;
const prefix = cellMatrix.rows[currentRowCount - 1];
for (let i = 0; i < rowsToAdd; i++) {
cellMatrix.rows.push({
...prefix,
rowId: currentRowCount + i,
idx: currentRowCount + i,
top: prefix.bottom,
bottom: prefix.bottom + prefix.height || CellMatrix.DEFAULT_ROW_HEIGHT,
});
}
updated = true;
}

// If needed, add a new status column that returns only when the grid is actually updated
return updated ? { ...state, cellMatrix } : state;
};
9 changes: 9 additions & 0 deletions src/lib/Functions/getDerivedStateFromProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export function getDerivedStateFromProps(
state = stateDeriverWithProps(state)(updateResponsiveSticky)

state = stateDeriverWithProps(state)(disableVirtualScrolling)

state = stateDeriverWithProps(state)(allowExtendPasteRange)

if (hasChanged) {
state = stateDeriverWithProps(state)(updateCellMatrix);
Expand Down Expand Up @@ -174,6 +176,13 @@ function disableVirtualScrolling(props: ReactGridProps, state: State): State {
}
}

function allowExtendPasteRange(props: ReactGridProps, state: State): State {
return {
...state,
allowExtendPasteRange: !!props.allowExtendPasteRange
}
}

export function appendHighlights(props: ReactGridProps, state: State): State {
const highlights = props.highlights?.filter(highlight => state.cellMatrix.rowIndexLookup[highlight.rowId] !== undefined &&
state.cellMatrix.columnIndexLookup[highlight.columnId] !== undefined
Expand Down
32 changes: 28 additions & 4 deletions src/lib/Functions/pasteData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Location } from "../Model/InternalModel";
import { tryAppendChangeHavingGroupId } from "./tryAppendChangeHavingGroupId";
import { getActiveSelectedRange } from "./getActiveSelectedRange";
import { newLocation } from "./newLocation";
import { expandGridIfNeeded } from "./expandGridIfNeeded";

export function pasteData(state: State, rows: Compatible<Cell>[][]): State {
const activeSelectedRange = getActiveSelectedRange(state);
Expand All @@ -12,7 +13,7 @@ export function pasteData(state: State, rows: Compatible<Cell>[][]): State {
activeSelectedRange.rows.forEach((row) =>
activeSelectedRange.columns.forEach((column) => {
state = tryAppendChangeHavingGroupId(
state,
state,
newLocation(row, column),
rows[0][0]
) as State;
Expand All @@ -35,20 +36,43 @@ export function pasteData(state: State, rows: Compatible<Cell>[][]): State {
lastLocation,
cell
) as State;
} else {
if (!state.allowExtendPasteRange) return;
const expandGridIfNeededState = expandGridIfNeeded(
state,
rowIdx,
columnIdx
);
lastLocation = expandGridIfNeededState.cellMatrix.getLocation(
rowIdx,
columnIdx
);
state = tryAppendChangeHavingGroupId(
expandGridIfNeededState,
lastLocation,
cell
) as State;
}
})
);
if (!lastLocation) {
return state;
}

const newRange = cellMatrix.getRange(activeSelectedRange.first, lastLocation);
const newRange = cellMatrix.getRange(
activeSelectedRange.first,
lastLocation
);

if (state?.props?.onSelectionChanging && !state.props.onSelectionChanging([newRange])) {
if (
state?.props?.onSelectionChanging &&
!state.props.onSelectionChanging([newRange])
) {
return state;
}

state?.props?.onSelectionChanged && state.props.onSelectionChanged([newRange]);
state?.props?.onSelectionChanged &&
state.props.onSelectionChanged([newRange]);

return {
...state,
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Model/PublicModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export interface ReactGridProps {
readonly enableGroupIdRender?: boolean;
/** Set `true` to disable virtual scrolling (by default `false`) */
readonly disableVirtualScrolling?: boolean;
/** Set `true` to allow pasting cells outside of the grid (by default `false`) */
readonly allowExtendPasteRange?: boolean;
/**
* Horizontal breakpoint in percents (%) of ReactGrid scrollable parent element width.
* Disables sticky when the sum of the sizes of sticky panes overflows
Expand Down
2 changes: 2 additions & 0 deletions src/lib/Model/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface State<TCellMatrix extends CellMatrix = CellMatrix, TBehavior ex
readonly enableColumnSelection: boolean;
readonly enableRowSelection: boolean;
readonly disableVirtualScrolling: boolean;
readonly allowExtendPasteRange: boolean;
readonly contextMenuPosition: { top: number; left: number };
readonly lineOrientation: Orientation;
readonly linePosition: number;
Expand Down Expand Up @@ -104,4 +105,5 @@ export const defaultStateFields = {
rightStickyColumns: undefined,
bottomStickyRows: undefined,
disableVirtualScrolling: false,
allowExtendPasteRange: false,
}
45 changes: 39 additions & 6 deletions src/test/TestGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,15 +320,44 @@ export const TestGrid: React.FC<TestGridProps> = (props) => {
// eslint-disable-next-line
rows[0].cells.find((cell) => cell.type === "text" && cell.text);


const handleChanges = (changes: CellChange<TestGridCells>[]) => {
setRows((prevRows) => {
const currentRows = [...prevRows];
const currentColumns = [...columns];
changes.forEach((change) => {
const changeRowIdx = prevRows.findIndex(
(el) => el.rowId === change.rowId
);
const changeColumnIdx = columns.findIndex(
let changeColumnIdx = currentColumns.findIndex(
(el) => el.columnId === change.columnId
);
// Extension column
if (changeColumnIdx === -1) {
currentColumns.push({
columnId: change.columnId,
} as Column);
setColumns(currentColumns);
changeColumnIdx = currentColumns.findIndex(
(el) => el.columnId === change.columnId
);
}
let changeRowIdx = currentRows.findIndex(
(el) => el.rowId === change.rowId
);
// Extension line
if (changeRowIdx === -1) {
const _cells = currentColumns.map((_c) => {
return {
type: "text",
text: "",
};
});
currentRows.push({
rowId: change.rowId,
cells: _cells as TestGridCells[],
});
changeRowIdx = currentRows.findIndex(
(el) => el.rowId === change.rowId
);
}
if (change.type === "flag") {
// console.log(change.newCell.text);
}
Expand All @@ -338,9 +367,9 @@ export const TestGrid: React.FC<TestGridProps> = (props) => {
if (change.type === "checkbox") {
// console.log(change.previousCell.checked);
}
prevRows[changeRowIdx].cells[changeColumnIdx] = change.newCell;
currentRows[changeRowIdx].cells[changeColumnIdx] = change.newCell;
});
return [...prevRows];
return [...currentRows];
});
};

Expand Down Expand Up @@ -544,6 +573,7 @@ export const TestGrid: React.FC<TestGridProps> = (props) => {
onSelectionChanged={handleSelectionChanged}
onSelectionChanging={handleSelectionChanging}
moveRightOnEnter={config.moveRightOnEnter}
allowExtendPasteRange={config.allowExtendPasteRange}
/>}
{config.additionalContent &&
<div style={{ height: `${config.rgViewportHeight}px`, backgroundColor: '#fafff3' }}>
Expand Down Expand Up @@ -636,6 +666,9 @@ export const TestGridOptionsSelect: React.FC = () => {
<option value="/disableVirtualScrolling">
Disable virtual scrolling
</option>
<option value="/allowExtendPasteRange">
Copy a range of cells and paste it into another range, extending the target range if it is too small.
</option>
</select>
</form>
);
Expand Down
7 changes: 7 additions & 0 deletions src/test/testEnvConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const config: TestConfig = {
enableGroupIdRender: true,
disableVirtualScrolling: false,
moveRightOnEnter: true,
allowExtendPasteRange: false,

cellHeight: 25,
cellWidth: 150,
Expand Down Expand Up @@ -84,6 +85,11 @@ export const config: TestConfig = {
/**
* Optional properties to override main config
*/
export const allowExtendPasteRangeConfig: TestConfig = {
...config,
allowExtendPasteRange: true,
}

export const enablePinnedToBodyConfig: TestConfig = {
...config,
pinToBody: true,
Expand Down Expand Up @@ -210,6 +216,7 @@ export interface TestConfig {
enableGroupIdRender: boolean;
disableVirtualScrolling: boolean;
moveRightOnEnter: boolean;
allowExtendPasteRange: boolean;

columns: number;
rows: number;
Expand Down