diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridSelection/useGridSelectionContext.tsx b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridSelection/useGridSelectionContext.tsx index 36a3b1628e..62ecc5e931 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridSelection/useGridSelectionContext.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridSelection/useGridSelectionContext.tsx @@ -39,6 +39,11 @@ export function useGridSelectionContext(tableData: ITableData) { const lastRowIdx = Math.max(startPosition, lastPosition); for (let rowIdx = firstRowIdx; rowIdx <= lastRowIdx; rowIdx++) { + if (isRowSelected(rowIdx)) { + selectedCells.delete(rowIdx); + continue; + } + if (temporary) { temporarySelectedCells.set(rowIdx, rowSelection); } else { @@ -48,19 +53,11 @@ export function useGridSelectionContext(tableData: ITableData) { }), [selectedCells, temporarySelectedCells]); const isRowSelected = useCallback((rowIdx: number) => { - if (!tableData) { - throw new Error('Table data must be provided'); - } - const columnsLength = tableData.columns?.length; return selectedCells.get(rowIdx)?.length === columnsLength; }, [tableData, selectedCells]); - const unSelectRow = useCallback((rowIdx: number) => { - selectedCells.delete(rowIdx); - }, [selectedCells]); - const selectRange = useCallback(action( (startPosition: number, lastPosition: number, columns: number[], multiple: boolean, temporary = false) => { if (!multiple) { @@ -118,15 +115,6 @@ export function useGridSelectionContext(tableData: ITableData) { return result; }, [selectedCells, tableData]); - const unSelectColumn = useCallback((columnIndex: number) => { - const rowsLength = tableData.rows?.length || 0; - - for (let rowIdx = 0; rowIdx < rowsLength; rowIdx++) { - const rowSelection = selectedCells.get(rowIdx) || []; - selectedCells.set(rowIdx, [...rowSelection.filter(colIdx => colIdx !== columnIndex)]); - } - }, [selectedCells, tableData]); - const selectColumn = useCallback(action((columnKey: string, multiple: boolean) => { if (!multiple) { selectedCells.clear(); @@ -135,15 +123,17 @@ export function useGridSelectionContext(tableData: ITableData) { const rowsLength = tableData.rows?.length || 0; const columnIndex = Number(columnKey); - if (isColumnSelected(columnIndex)) { - unSelectColumn(columnIndex); - } else { - for (let rowIdx = 0; rowIdx < rowsLength; rowIdx++) { - const rowSelection = selectedCells.get(rowIdx) || []; + const isSelected = isColumnSelected(columnIndex); + + for (let rowIdx = 0; rowIdx < rowsLength; rowIdx++) { + const rowSelection = selectedCells.get(rowIdx) || []; + if (isSelected) { + selectedCells.set(rowIdx, [...rowSelection.filter(colIdx => colIdx !== columnIndex)]); + } else { selectedCells.set(rowIdx, [...rowSelection, columnIndex]); } } - }), [tableData, selectedCells, isColumnSelected, unSelectColumn]); + }), [tableData, selectedCells, isColumnSelected]); const selectTable = useCallback(() => { const rowsLength = tableData.rows?.length || 0; @@ -216,11 +206,8 @@ export function useGridSelectionContext(tableData: ITableData) { } if (isIndexColumn) { - if (multiple && isRowSelected(rowIdx)) { - unSelectRow(rowIdx); - } else { - selectRows(rowIdx, rowIdx, multiple); - } + selectRows(rowIdx, rowIdx, multiple); + return; } @@ -241,8 +228,6 @@ export function useGridSelectionContext(tableData: ITableData) { isSelected, selectRows, selectCell, - isRowSelected, - unSelectRow, lastSelectedCell, updateMultiSelection, ]); diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridDragging.ts b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridDragging.ts index 5031221d29..0ef45002f2 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridDragging.ts +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridDragging.ts @@ -6,7 +6,9 @@ * you may not use this file except in compliance with the License. */ -import { useState, useCallback, useEffect } from 'react'; +import { useCallback, useEffect } from 'react'; + +import { useObjectRef } from '@cloudbeaver/core-blocks'; interface IDraggingPosition { idx: number; @@ -24,6 +26,14 @@ type DraggingCallback = ( event: React.MouseEvent | MouseEvent ) => void; +interface IDraggingState { + startDraggingCell: IDraggingPosition | null; + currentDraggingCell: IDraggingPosition | null; + startMousePosition: IMousePosition | null; + dragging: boolean; + mouseDown: boolean; +} + interface IDraggingCallbacks { onDragStart?: ( startPosition: IDraggingPosition, @@ -75,29 +85,31 @@ function isDraggingStarted(delta: number | null, threshold: number) { return delta > threshold; } -export function useGridDragging(callbacks: IDraggingCallbacks) { - const { onDragStart, onDragOver, onDragEnd } = callbacks; +export function useGridDragging(props: IDraggingCallbacks) { + const callbacks = useObjectRef(props); - const [startDraggingCell, setStartDraggingCell] = useState(null); - const [currentDraggingCell, setCurrentDraggingCell] = useState(null); - const [startMousePosition, setStartMousePosition] = useState(null); - const [isDragging, setDragging] = useState(false); - const [mouseDown, setMouseDown] = useState(false); + const state = useObjectRef({ + startDraggingCell: null, + currentDraggingCell: null, + startMousePosition: null, + dragging: false, + mouseDown: false, + }, {}); - const onMouseDownHandler = (event: React.MouseEvent) => { + const onMouseDownHandler = useCallback((event: React.MouseEvent) => { const position = getCellPositionFromEvent(event); if (!position) { return; } - setMouseDown(true); - setStartMousePosition({ ...startMousePosition, x: event.pageX, y: event.pageY }); - setStartDraggingCell({ idx: position.colIdx, rowIdx: position.rowIdx }); - }; + state.current.mouseDown = true; + state.current.startMousePosition = { x: event.pageX, y: event.pageY }; + state.current.startDraggingCell = { idx: position.colIdx, rowIdx: position.rowIdx }; + }, []); - const onMouseMoveHandler = (event: React.MouseEvent) => { - if (!mouseDown) { + const onMouseMoveHandler = useCallback((event: React.MouseEvent) => { + if (!state.current.mouseDown) { return; } @@ -107,33 +119,33 @@ export function useGridDragging(callbacks: IDraggingCallbacks) { return; } - if (!isDragging) { - const delta = getDelta(startMousePosition, { x: event.pageX, y: event.pageY }); + if (!state.current.dragging) { + const delta = getDelta(state.current.startMousePosition, { x: event.pageX, y: event.pageY }); if (!isDraggingStarted(delta, THRESHOLD)) { return; } - if (onDragStart && startDraggingCell) { - onDragStart(startDraggingCell, event); + if (callbacks.current.onDragStart && state.current.startDraggingCell) { + callbacks.current.onDragStart(state.current.startDraggingCell, event); } - setDragging(true); + state.current.dragging = true; return; } // check if the new cell is equal to the previous cell - if (position.rowIdx === currentDraggingCell?.rowIdx - && position.colIdx === currentDraggingCell.idx) { + if (position.rowIdx === state.current.currentDraggingCell?.rowIdx + && position.colIdx === state.current.currentDraggingCell.idx) { return; } - setCurrentDraggingCell({ idx: position.colIdx, rowIdx: position.rowIdx }); + state.current.currentDraggingCell = { idx: position.colIdx, rowIdx: position.rowIdx }; - if (onDragOver) { - onDragOver( + if (callbacks.current.onDragOver) { + callbacks.current.onDragOver( { - idx: startDraggingCell!.idx, - rowIdx: startDraggingCell!.rowIdx, + idx: state.current.startDraggingCell!.idx, + rowIdx: state.current.startDraggingCell!.rowIdx, }, { idx: position.colIdx, @@ -141,33 +153,33 @@ export function useGridDragging(callbacks: IDraggingCallbacks) { }, event); } - }; + }, []); const onMouseUpHandler = useCallback((event: React.MouseEvent | MouseEvent) => { - setMouseDown(false); - setStartMousePosition(null); + state.current.mouseDown = false; + state.current.startMousePosition = null; - if (!isDragging || !startDraggingCell || !currentDraggingCell) { + if (!state.current.dragging || !state.current.startDraggingCell || !state.current.currentDraggingCell) { return; } - if (onDragEnd) { - onDragEnd( + if (callbacks.current.onDragEnd) { + callbacks.current.onDragEnd( { - idx: startDraggingCell.idx, - rowIdx: startDraggingCell.rowIdx, + idx: state.current.startDraggingCell.idx, + rowIdx: state.current.startDraggingCell.rowIdx, }, { - idx: currentDraggingCell.idx, - rowIdx: currentDraggingCell.rowIdx, + idx: state.current.currentDraggingCell.idx, + rowIdx: state.current.currentDraggingCell.rowIdx, }, event); } - setDragging(false); - setStartDraggingCell(null); - setCurrentDraggingCell(null); - }, [isDragging, currentDraggingCell, startDraggingCell, onDragEnd]); + state.current.dragging = false; + state.current.startMousePosition = null; + state.current.currentDraggingCell = null; + }, []); useEffect(() => { document.addEventListener('mouseup', onMouseUpHandler);