refactor(actions): addSelectedElements => addSelectedNodes, addSelectedEdges

This commit is contained in:
moklick
2021-11-26 15:18:27 +01:00
parent a032306408
commit d260abec75
9 changed files with 46 additions and 39 deletions
+13 -9
View File
@@ -1,5 +1,5 @@
import { useEffect, useState, useCallback } from 'react'; import { useEffect, useState } from 'react';
import ReactFlow, { Node, Edge, applyNodeChanges, NodeChange } from 'react-flow-renderer'; import ReactFlow, { Node, Edge, useNodesState, useEdgesState } from 'react-flow-renderer';
import './updatenode.css'; import './updatenode.css';
@@ -11,8 +11,8 @@ const initialNodes: Node[] = [
const initialEdges: Edge[] = [{ id: 'e1-2', source: '1', target: '2' }]; const initialEdges: Edge[] = [{ id: 'e1-2', source: '1', target: '2' }];
const UpdateNode = () => { const UpdateNode = () => {
const [nodes, setNodes] = useState<Node[]>(initialNodes); const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges] = useState<Edge[]>(initialEdges); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const [nodeName, setNodeName] = useState<string>('Node 1'); const [nodeName, setNodeName] = useState<string>('Node 1');
const [nodeBg, setNodeBg] = useState<string>('#eee'); const [nodeBg, setNodeBg] = useState<string>('#eee');
@@ -60,12 +60,16 @@ const UpdateNode = () => {
); );
}, [nodeHidden]); }, [nodeHidden]);
const onNodesChange = useCallback((changes: NodeChange[]) => {
setNodes((ns) => applyNodeChanges(changes, ns));
}, []);
return ( return (
<ReactFlow nodes={nodes} edges={edges} defaultZoom={1.5} minZoom={0.2} maxZoom={4} onNodesChange={onNodesChange}> <ReactFlow
nodes={nodes}
edges={edges}
defaultZoom={1.5}
minZoom={0.2}
maxZoom={4}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
>
<div className="updatenode__controls"> <div className="updatenode__controls">
<label>label:</label> <label>label:</label>
<input value={nodeName} onChange={(evt) => setNodeName(evt.target.value)} /> <input value={nodeName} onChange={(evt) => setNodeName(evt.target.value)} />
+1 -1
View File
@@ -1,5 +1,5 @@
// These components are not used by React Flow directly // These components are not used by React Flow directly
// but the user can add them as children of a React Flow component // They can be added as children of a React Flow component
export { default as MiniMap } from './MiniMap'; export { default as MiniMap } from './MiniMap';
export { default as Controls, ControlButton } from './Controls'; export { default as Controls, ControlButton } from './Controls';
+3 -3
View File
@@ -9,7 +9,7 @@ import { EdgeAnchor } from './EdgeAnchor';
import { getMarkerId } from '../../utils/graph'; import { getMarkerId } from '../../utils/graph';
const selector = (s: ReactFlowState) => ({ const selector = (s: ReactFlowState) => ({
addSelectedElements: s.addSelectedElements, addSelectedEdges: s.addSelectedEdges,
setConnectionNodeId: s.setConnectionNodeId, setConnectionNodeId: s.setConnectionNodeId,
unsetNodesSelection: s.unsetNodesSelection, unsetNodesSelection: s.unsetNodesSelection,
setPosition: s.setConnectionPosition, setPosition: s.setConnectionPosition,
@@ -57,7 +57,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
markerStart, markerStart,
}: WrapEdgeProps): JSX.Element | null => { }: WrapEdgeProps): JSX.Element | null => {
const store = useStoreApi(); const store = useStoreApi();
const { addSelectedElements, setConnectionNodeId, unsetNodesSelection, setPosition, connectionMode } = useStore( const { addSelectedEdges, setConnectionNodeId, unsetNodesSelection, setPosition, connectionMode } = useStore(
selector, selector,
shallow shallow
); );
@@ -100,7 +100,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => { (event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
if (elementsSelectable) { if (elementsSelectable) {
unsetNodesSelection(); unsetNodesSelection();
addSelectedElements([edgeElement]); addSelectedEdges([edgeElement.id]);
} }
onClick?.(event, edgeElement); onClick?.(event, edgeElement);
+5 -5
View File
@@ -8,7 +8,7 @@ import { Provider } from '../../contexts/NodeIdContext';
import { NodeProps, WrapNodeProps, ReactFlowState } from '../../types'; import { NodeProps, WrapNodeProps, ReactFlowState } from '../../types';
const selector = (s: ReactFlowState) => ({ const selector = (s: ReactFlowState) => ({
addSelectedElements: s.addSelectedElements, addSelectedNodes: s.addSelectedNodes,
unsetNodesSelection: s.unsetNodesSelection, unsetNodesSelection: s.unsetNodesSelection,
updateNodePosition: s.updateNodePosition, updateNodePosition: s.updateNodePosition,
updateNodeDimensions: s.updateNodeDimensions, updateNodeDimensions: s.updateNodeDimensions,
@@ -54,7 +54,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
noDragClassName, noDragClassName,
}: WrapNodeProps) => { }: WrapNodeProps) => {
const { const {
addSelectedElements, addSelectedNodes,
unselectNodesAndEdges, unselectNodesAndEdges,
unsetNodesSelection, unsetNodesSelection,
updateNodePosition, updateNodePosition,
@@ -130,7 +130,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
unsetNodesSelection(); unsetNodesSelection();
if (!selected) { if (!selected) {
addSelectedElements([node]); addSelectedNodes([node.id]);
} }
} }
@@ -148,7 +148,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
unsetNodesSelection(); unsetNodesSelection();
if (!selected) { if (!selected) {
addSelectedElements([node]); addSelectedNodes([node.id]);
} }
} else if (!selectNodesOnDrag && !selected && isSelectable) { } else if (!selectNodesOnDrag && !selected && isSelectable) {
unselectNodesAndEdges(); unselectNodesAndEdges();
@@ -178,7 +178,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
// Because of that we set dragging to true inside the onDrag handler and handle the click here // Because of that we set dragging to true inside the onDrag handler and handle the click here
if (!dragging) { if (!dragging) {
if (isSelectable && !selectNodesOnDrag && !selected) { if (isSelectable && !selectNodesOnDrag && !selected) {
addSelectedElements([node]); addSelectedNodes([node.id]);
} }
onClick?.(event as MouseEvent, node); onClick?.(event as MouseEvent, node);
+1 -7
View File
@@ -88,13 +88,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source); const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source);
const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(nodeInternals, edge.target); const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(nodeInternals, edge.target);
if (!sourceIsValid) { if (!sourceIsValid || !targetIsValid) {
console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`);
return null;
}
if (!targetIsValid) {
console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`);
return null; return null;
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import { ReactFlowState } from '../types';
const updateSizeSelector = (state: ReactFlowState) => state.updateSize; const updateSizeSelector = (state: ReactFlowState) => state.updateSize;
function useResizeHandler(rendererNode: MutableRefObject<HTMLDivElement | null>) { function useResizeHandler(rendererNode: MutableRefObject<HTMLDivElement | null>): void {
const updateSize = useStore(updateSizeSelector); const updateSize = useStore(updateSizeSelector);
useEffect(() => { useEffect(() => {
+18 -10
View File
@@ -27,7 +27,7 @@ import {
XYPosition, XYPosition,
ReactFlowStore, ReactFlowStore,
} from '../types'; } from '../types';
import { isNode, isEdge, getRectOfNodes, getNodesInside, getConnectedEdges } from '../utils/graph'; import { getRectOfNodes, getNodesInside, getConnectedEdges } from '../utils/graph';
import { getHandleBounds } from '../components/Nodes/utils'; import { getHandleBounds } from '../components/Nodes/utils';
import { createNodeInternals, createNodeOrEdgeSelectionChange } from './utils'; import { createNodeInternals, createNodeOrEdgeSelectionChange } from './utils';
@@ -249,28 +249,36 @@ const createStore = () =>
set(stateUpdate); set(stateUpdate);
}, },
addSelectedElements: (selectedElementsArr: Array<Node | Edge>) => { addSelectedNodes: (selectedNodeIds: string[]) => {
const { multiSelectionActive, onNodesChange, onEdgesChange, nodeInternals, edges } = get(); const { multiSelectionActive, onNodesChange, nodeInternals } = get();
// @TODO: work with nodeInternals instead of converting it to an array // @TODO: work with nodeInternals instead of converting it to an array
const nodes = Array.from(nodeInternals).map(([_, node]) => node); const nodes = Array.from(nodeInternals).map(([_, node]) => node);
let changedNodes; let changedNodes;
let changedEdges;
if (multiSelectionActive) { if (multiSelectionActive) {
changedNodes = selectedElementsArr.filter(isNode).map(createNodeOrEdgeSelectionChange(true)); changedNodes = selectedNodeIds.map(createNodeOrEdgeSelectionChange(true));
changedEdges = selectedElementsArr.filter(isEdge).map(createNodeOrEdgeSelectionChange(true));
} else { } else {
changedNodes = nodes.map((node) => changedNodes = nodes.map((node) =>
createNodeOrEdgeSelectionChange(selectedElementsArr.some((e) => e.id === node.id))(node) createNodeOrEdgeSelectionChange(selectedNodeIds.some((nodeId) => nodeId === node.id))(node.id)
);
changedEdges = edges.map((edge) =>
createNodeOrEdgeSelectionChange(selectedElementsArr.some((e) => e.id === edge.id))(edge)
); );
} }
if (changedNodes.length) { if (changedNodes.length) {
onNodesChange?.(changedNodes as NodeChange[]); onNodesChange?.(changedNodes as NodeChange[]);
} }
},
addSelectedEdges: (selectedEdgeIds: string[]) => {
const { multiSelectionActive, onEdgesChange, edges } = get();
let changedEdges;
if (multiSelectionActive) {
changedEdges = selectedEdgeIds.map(createNodeOrEdgeSelectionChange(true));
} else {
changedEdges = edges.map((edge) =>
createNodeOrEdgeSelectionChange(selectedEdgeIds.some((edgeId) => edgeId === edge.id))(edge.id)
);
}
if (changedEdges.length) { if (changedEdges.length) {
onEdgesChange?.(changedEdges as EdgeChange[]); onEdgesChange?.(changedEdges as EdgeChange[]);
+2 -2
View File
@@ -105,8 +105,8 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals)
return nextNodeInternals; return nextNodeInternals;
} }
export const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge) => ({ export const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge | string) => ({
id: item.id, id: typeof item === 'string' ? item : item.id,
type: 'select', type: 'select',
selected, selected,
}); });
+2 -1
View File
@@ -182,7 +182,8 @@ export type ReactFlowActions = {
unsetNodesSelection: () => void; unsetNodesSelection: () => void;
resetSelectedElements: () => void; resetSelectedElements: () => void;
unselectNodesAndEdges: () => void; unselectNodesAndEdges: () => void;
addSelectedElements: (elements: Elements) => void; addSelectedNodes: (nodeIds: string[]) => void;
addSelectedEdges: (edgeIds: string[]) => void;
updateTransform: (transform: Transform) => void; updateTransform: (transform: Transform) => void;
updateSize: (size: Dimensions) => void; updateSize: (size: Dimensions) => void;
initD3Zoom: (payload: InitD3ZoomPayload) => void; initD3Zoom: (payload: InitD3ZoomPayload) => void;