feat(plugin-data-spreadsheet-new): CB-696 replaced react state with ref object

This commit is contained in:
Naumov Alexey
2021-02-17 17:50:46 +03:00
parent a00c9f5eeb
commit 172ba71532
2 changed files with 68 additions and 71 deletions
@@ -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,
]);
@@ -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<HTMLDivElement, 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<IDraggingPosition | null>(null);
const [currentDraggingCell, setCurrentDraggingCell] = useState<IDraggingPosition | null>(null);
const [startMousePosition, setStartMousePosition] = useState<IMousePosition | null>(null);
const [isDragging, setDragging] = useState(false);
const [mouseDown, setMouseDown] = useState(false);
const state = useObjectRef<IDraggingState>({
startDraggingCell: null,
currentDraggingCell: null,
startMousePosition: null,
dragging: false,
mouseDown: false,
}, {});
const onMouseDownHandler = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const onMouseDownHandler = useCallback((event: React.MouseEvent<HTMLDivElement, 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<HTMLDivElement, MouseEvent>) => {
if (!mouseDown) {
const onMouseMoveHandler = useCallback((event: React.MouseEvent<HTMLDivElement, 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<HTMLDivElement, 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);