feat: allow customisation of how the select box works.

This commit is contained in:
Jack Fishwick
2022-11-22 11:05:45 +00:00
parent f25c7fe8a2
commit 09ebd0c84a
5 changed files with 18 additions and 2 deletions
@@ -8,7 +8,7 @@ import shallow from 'zustand/shallow';
import { useStore, useStoreApi } from '../../hooks/useStore'; import { useStore, useStoreApi } from '../../hooks/useStore';
import { getSelectionChanges } from '../../utils/changes'; import { getSelectionChanges } from '../../utils/changes';
import { getConnectedEdges, getNodesInside } from '../../utils/graph'; import { getConnectedEdges, getNodesInside } from '../../utils/graph';
import type { XYPosition, ReactFlowState, NodeChange, EdgeChange, Rect } from '../../types'; import type { XYPosition, ReactFlowState, NodeChange, EdgeChange, Rect, ReactFlowProps } from '../../types';
type SelectionRect = Rect & { type SelectionRect = Rect & {
startX: number; startX: number;
@@ -19,6 +19,7 @@ type EventHandlers = { [key: string]: React.MouseEventHandler | React.WheelEvent
type UserSelectionProps = { type UserSelectionProps = {
isSelectionMode: boolean; isSelectionMode: boolean;
selectBoxMode?: ReactFlowProps['selectBoxMode'];
onSelectionStart?: (e: React.MouseEvent) => void; onSelectionStart?: (e: React.MouseEvent) => void;
onSelectionEnd?: (e: React.MouseEvent) => void; onSelectionEnd?: (e: React.MouseEvent) => void;
onClick?: (e: React.MouseEvent) => void; onClick?: (e: React.MouseEvent) => void;
@@ -60,6 +61,7 @@ const selector = (s: ReactFlowState) => ({
const UserSelection = memo( const UserSelection = memo(
({ ({
isSelectionMode, isSelectionMode,
selectBoxMode = 'Contained',
onSelectionStart, onSelectionStart,
onSelectionEnd, onSelectionEnd,
onClick, onClick,
@@ -130,7 +132,14 @@ const UserSelection = memo(
const { nodeInternals, edges, transform, onNodesChange, onEdgesChange, nodeOrigin } = store.getState(); const { nodeInternals, edges, transform, onNodesChange, onEdgesChange, nodeOrigin } = store.getState();
const nodes = Array.from(nodeInternals.values()); const nodes = Array.from(nodeInternals.values());
const selectedNodes = getNodesInside(nodeInternals, nextUserSelectRect, transform, true, true, nodeOrigin); const selectedNodes = getNodesInside(
nodeInternals,
nextUserSelectRect,
transform,
selectBoxMode === 'Overlap',
true,
nodeOrigin
);
const selectedEdgeIds = getConnectedEdges(selectedNodes, edges).map((e) => e.id); const selectedEdgeIds = getConnectedEdges(selectedNodes, edges).map((e) => e.id);
const selectedNodeIds = selectedNodes.map((n) => n.id); const selectedNodeIds = selectedNodes.map((n) => n.id);
@@ -45,6 +45,7 @@ const FlowRenderer = ({
onMoveEnd, onMoveEnd,
selectionKeyCode, selectionKeyCode,
selectBoxOnDrag, selectBoxOnDrag,
selectBoxMode,
onSelectionStart, onSelectionStart,
onSelectionEnd, onSelectionEnd,
multiSelectionKeyCode, multiSelectionKeyCode,
@@ -123,6 +124,7 @@ const FlowRenderer = ({
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
onWheel={onWheel} onWheel={onWheel}
isSelectionMode={isSelectionMode} isSelectionMode={isSelectionMode}
selectBoxMode={selectBoxMode}
> >
{children} {children}
{nodesSelectionActive && ( {nodesSelectionActive && (
@@ -59,6 +59,7 @@ const GraphView = ({
connectionLineContainerStyle, connectionLineContainerStyle,
selectionKeyCode, selectionKeyCode,
selectBoxOnDrag, selectBoxOnDrag,
selectBoxMode,
multiSelectionKeyCode, multiSelectionKeyCode,
zoomActivationKeyCode, zoomActivationKeyCode,
deleteKeyCode, deleteKeyCode,
@@ -114,6 +115,7 @@ const GraphView = ({
deleteKeyCode={deleteKeyCode} deleteKeyCode={deleteKeyCode}
selectionKeyCode={selectionKeyCode} selectionKeyCode={selectionKeyCode}
selectBoxOnDrag={selectBoxOnDrag} selectBoxOnDrag={selectBoxOnDrag}
selectBoxMode={selectBoxMode}
onSelectionStart={onSelectionStart} onSelectionStart={onSelectionStart}
onSelectionEnd={onSelectionEnd} onSelectionEnd={onSelectionEnd}
multiSelectionKeyCode={multiSelectionKeyCode} multiSelectionKeyCode={multiSelectionKeyCode}
@@ -102,6 +102,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
deleteKeyCode = 'Backspace', deleteKeyCode = 'Backspace',
selectionKeyCode = 'Shift', selectionKeyCode = 'Shift',
selectBoxOnDrag = false, selectBoxOnDrag = false,
selectBoxMode = 'Contained',
multiSelectionKeyCode = 'Meta', multiSelectionKeyCode = 'Meta',
zoomActivationKeyCode = 'Meta', zoomActivationKeyCode = 'Meta',
snapToGrid = false, snapToGrid = false,
@@ -197,6 +198,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
connectionLineContainerStyle={connectionLineContainerStyle} connectionLineContainerStyle={connectionLineContainerStyle}
selectionKeyCode={selectionKeyCode} selectionKeyCode={selectionKeyCode}
selectBoxOnDrag={selectBoxOnDrag} selectBoxOnDrag={selectBoxOnDrag}
selectBoxMode={selectBoxMode}
deleteKeyCode={deleteKeyCode} deleteKeyCode={deleteKeyCode}
multiSelectionKeyCode={multiSelectionKeyCode} multiSelectionKeyCode={multiSelectionKeyCode}
zoomActivationKeyCode={zoomActivationKeyCode} zoomActivationKeyCode={zoomActivationKeyCode}
@@ -97,6 +97,7 @@ export type ReactFlowProps = HTMLAttributes<HTMLDivElement> & {
deleteKeyCode?: KeyCode | null; deleteKeyCode?: KeyCode | null;
selectionKeyCode?: KeyCode | null; selectionKeyCode?: KeyCode | null;
selectBoxOnDrag?: boolean; selectBoxOnDrag?: boolean;
selectBoxMode?: 'Overlap' | 'Contained';
multiSelectionKeyCode?: KeyCode | null; multiSelectionKeyCode?: KeyCode | null;
zoomActivationKeyCode?: KeyCode | null; zoomActivationKeyCode?: KeyCode | null;
snapToGrid?: boolean; snapToGrid?: boolean;