From e3fe94014eda5019af8f42d72a75a6a3c15ae046 Mon Sep 17 00:00:00 2001 From: phen0menon Date: Mon, 27 Sep 2021 23:21:18 +0300 Subject: [PATCH 1/2] Implement onPaste event, add `autoPadRowsOnPaste` flag --- src/Spreadsheet.tsx | 22 ++++++++++++++++++++-- src/actions.ts | 9 +++++++-- src/reducer.ts | 22 +++++++++++++++------- src/types.ts | 1 + src/util.test.ts | 1 + 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/Spreadsheet.tsx b/src/Spreadsheet.tsx index 386c5748..756ecbd4 100644 --- a/src/Spreadsheet.tsx +++ b/src/Spreadsheet.tsx @@ -70,6 +70,11 @@ export type Props = { * Defaults to: `false`. */ hideColumnIndicators?: boolean; + /** + * If set to true, automatically creates missing rows when inserting + * Defaults to: `true` + */ + autoPadRowsOnPaste?: boolean; // Custom Components /** Component rendered above each column. */ ColumnIndicator?: Types.ColumnIndicatorComponent; @@ -105,6 +110,8 @@ export type Props = { onSelect?: (selected: Point.Point[]) => void; /** Callback called when Spreadsheet's active cell changes. */ onActivate?: (active: Point.Point) => void; + /** Callback called when Spreadhseet data pasted */ + onPaste?: (selected: Point.Point[]) => void; /** Callback called when the Spreadsheet loses focus */ onBlur?: () => void; onCellCommit?: ( @@ -127,6 +134,7 @@ const Spreadsheet = ( rowLabels, hideColumnIndicators, hideRowIndicators, + autoPadRowsOnPaste = true, onKeyDown, Table = DefaultTable, Row = DefaultRow, @@ -140,6 +148,7 @@ const Spreadsheet = ( onChange = () => {}, onModeChange = () => {}, onSelect = () => {}, + onPaste = () => {}, onActivate = () => {}, onBlur = () => {}, onCellCommit = () => {}, @@ -168,6 +177,7 @@ const Spreadsheet = ( const prevStateRef = React.useRef>({ ...INITIAL_STATE, data: props.data, + pasted: null, selected: null, copied: PointMap.from([]), bindings: PointMap.from([]), @@ -177,8 +187,8 @@ const Spreadsheet = ( const copy = React.useCallback(() => dispatch(Actions.copy()), [dispatch]); const cut = React.useCallback(() => dispatch(Actions.cut()), [dispatch]); const paste = React.useCallback( - (data) => dispatch(Actions.paste(data)), - [dispatch] + (data) => dispatch(Actions.paste(data, autoPadRowsOnPaste)), + [dispatch, autoPadRowsOnPaste] ); const onKeyDownAction = React.useCallback( (event) => dispatch(Actions.keyDown(event)), @@ -228,6 +238,13 @@ const Spreadsheet = ( onSelect(points); } + if (state.pasted !== prevState.pasted) { + const points = state.pasted + ? Array.from(PointRange.iterate(state.pasted)) + : []; + onPaste(points); + } + if (state.active !== prevState.active) { if (state.active) { onActivate(state.active); @@ -250,6 +267,7 @@ const Spreadsheet = ( onChange, onModeChange, onSelect, + onPaste, rowLabels, columnLabels, ]); diff --git a/src/actions.ts b/src/actions.ts index 8dee5738..848ec049 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -47,9 +47,14 @@ export const setCellDimensions = createAction< export const copy = createAction("COPY"); export const cut = createAction("CUT"); export const paste = createAction< - (data: string) => { payload: { data: string } }, + ( + data: string, + autoPadRowsOnPaste: boolean + ) => { payload: { data: string; autoPadRowsOnPaste: boolean } }, "PASTE" ->("PASTE", (data) => ({ payload: { data } })); +>("PASTE", (data, autoPadRowsOnPaste) => ({ + payload: { data, autoPadRowsOnPaste }, +})); export const edit = createAction("EDIT"); export const view = createAction("VIEW"); export const clear = createAction("CLEAR"); diff --git a/src/reducer.ts b/src/reducer.ts index bdaf6b3e..1298f324 100644 --- a/src/reducer.ts +++ b/src/reducer.ts @@ -26,6 +26,7 @@ export const INITIAL_STATE: Types.StoreState = { dragging: false, data: [], selected: null, + pasted: null, copied: PointMap.from([]), bindings: PointMap.from([]), lastCommit: null, @@ -110,7 +111,7 @@ const reducer = createReducer(INITIAL_STATE, (builder) => { }; }); builder.addCase(Actions.paste, (state, action) => { - const { data: text } = action.payload; + const { data: text, autoPadRowsOnPaste } = action.payload; const { active } = state; if (!active) { return; @@ -126,8 +127,11 @@ const reducer = createReducer(INITIAL_STATE, (builder) => { }; const copiedSize = Matrix.getSize(copiedMatrix); - const requiredRows = active.row + copiedSize.rows; - const paddedData = Matrix.padRows(state.data, requiredRows); + const paddedRowsCount = active.row + copiedSize.rows; + const requiredRowsCount = !autoPadRowsOnPaste + ? Math.min(paddedRowsCount, state.data.length) + : paddedRowsCount; + const paddedData = Matrix.padRows(state.data, requiredRowsCount); const { data, commit } = PointMap.reduce( (acc, value, point) => { @@ -165,13 +169,17 @@ const reducer = createReducer(INITIAL_STATE, (builder) => { copied, { data: paddedData, commit: [] } ); + + const selectedRange = PointRange.create(active, { + row: autoPadRowsOnPaste ? paddedRowsCount - 1 : requiredRowsCount - 1, + column: active.column + copiedSize.columns - 1, + }); + return { ...state, data, - selected: PointRange.create(active, { - row: active.row + copiedSize.rows - 1, - column: active.column + copiedSize.columns - 1, - }), + selected: selectedRange, + pasted: selectedRange, cut: false, hasPasted: true, mode: "view", diff --git a/src/types.ts b/src/types.ts index c27daa98..0a1edb28 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,6 +47,7 @@ export type Dimensions = { export type StoreState = { data: Matrix; selected: PointRange | null; + pasted: PointRange | null; copied: PointMap; hasPasted: boolean; cut: boolean; diff --git a/src/util.test.ts b/src/util.test.ts index 2d41727e..7e2c3234 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -60,6 +60,7 @@ const EXAMPLE_STATE: Types.StoreState = { dragging: false, data: EXAMPLE_DATA, selected: null, + pasted: null, copied: PointMap.from([]), bindings: PointMap.from([]), lastCommit: null, From 493797225fc1d2212e4ee07ca7cdc2ff4c8d4454 Mon Sep 17 00:00:00 2001 From: phen0menon Date: Mon, 27 Sep 2021 23:25:38 +0300 Subject: [PATCH 2/2] Improve `autoPadRowsOnPaste` flag description --- src/Spreadsheet.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Spreadsheet.tsx b/src/Spreadsheet.tsx index 756ecbd4..2d54d714 100644 --- a/src/Spreadsheet.tsx +++ b/src/Spreadsheet.tsx @@ -71,7 +71,7 @@ export type Props = { */ hideColumnIndicators?: boolean; /** - * If set to true, automatically creates missing rows when inserting + * If set to true, automatically creates missing rows when pasting from clipboard * Defaults to: `true` */ autoPadRowsOnPaste?: boolean;