mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat(plugin-data-spreadsheet-new): CB-696 replaced react state with ref object
This commit is contained in:
+15
-30
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user