Skip to content

Commit

Permalink
refactor(actions): addSelectedElements => addSelectedNodes, addSelect…
Browse files Browse the repository at this point in the history
…edEdges
  • Loading branch information
moklick committed Nov 26, 2021
1 parent a032306 commit d260abe
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 39 deletions.
22 changes: 13 additions & 9 deletions example/src/UpdateNode/index.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState, useCallback } from 'react';
import ReactFlow, { Node, Edge, applyNodeChanges, NodeChange } from 'react-flow-renderer';
import { useEffect, useState } from 'react';
import ReactFlow, { Node, Edge, useNodesState, useEdgesState } from 'react-flow-renderer';

import './updatenode.css';

Expand All @@ -11,8 +11,8 @@ const initialNodes: Node[] = [
const initialEdges: Edge[] = [{ id: 'e1-2', source: '1', target: '2' }];

const UpdateNode = () => {
const [nodes, setNodes] = useState<Node[]>(initialNodes);
const [edges, setEdges] = useState<Edge[]>(initialEdges);
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

const [nodeName, setNodeName] = useState<string>('Node 1');
const [nodeBg, setNodeBg] = useState<string>('#eee');
Expand Down Expand Up @@ -60,12 +60,16 @@ const UpdateNode = () => {
);
}, [nodeHidden]);

const onNodesChange = useCallback((changes: NodeChange[]) => {
setNodes((ns) => applyNodeChanges(changes, ns));
}, []);

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">
<label>label:</label>
<input value={nodeName} onChange={(evt) => setNodeName(evt.target.value)} />
Expand Down
2 changes: 1 addition & 1 deletion src/additional-components/index.ts
@@ -1,5 +1,5 @@
// 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 Controls, ControlButton } from './Controls';
Expand Down
6 changes: 3 additions & 3 deletions src/components/Edges/wrapEdge.tsx
Expand Up @@ -9,7 +9,7 @@ import { EdgeAnchor } from './EdgeAnchor';
import { getMarkerId } from '../../utils/graph';

const selector = (s: ReactFlowState) => ({
addSelectedElements: s.addSelectedElements,
addSelectedEdges: s.addSelectedEdges,
setConnectionNodeId: s.setConnectionNodeId,
unsetNodesSelection: s.unsetNodesSelection,
setPosition: s.setConnectionPosition,
Expand Down Expand Up @@ -57,7 +57,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
markerStart,
}: WrapEdgeProps): JSX.Element | null => {
const store = useStoreApi();
const { addSelectedElements, setConnectionNodeId, unsetNodesSelection, setPosition, connectionMode } = useStore(
const { addSelectedEdges, setConnectionNodeId, unsetNodesSelection, setPosition, connectionMode } = useStore(
selector,
shallow
);
Expand Down Expand Up @@ -100,7 +100,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
if (elementsSelectable) {
unsetNodesSelection();
addSelectedElements([edgeElement]);
addSelectedEdges([edgeElement.id]);
}

onClick?.(event, edgeElement);
Expand Down
10 changes: 5 additions & 5 deletions src/components/Nodes/wrapNode.tsx
Expand Up @@ -8,7 +8,7 @@ import { Provider } from '../../contexts/NodeIdContext';
import { NodeProps, WrapNodeProps, ReactFlowState } from '../../types';

const selector = (s: ReactFlowState) => ({
addSelectedElements: s.addSelectedElements,
addSelectedNodes: s.addSelectedNodes,
unsetNodesSelection: s.unsetNodesSelection,
updateNodePosition: s.updateNodePosition,
updateNodeDimensions: s.updateNodeDimensions,
Expand Down Expand Up @@ -54,7 +54,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
noDragClassName,
}: WrapNodeProps) => {
const {
addSelectedElements,
addSelectedNodes,
unselectNodesAndEdges,
unsetNodesSelection,
updateNodePosition,
Expand Down Expand Up @@ -130,7 +130,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
unsetNodesSelection();

if (!selected) {
addSelectedElements([node]);
addSelectedNodes([node.id]);
}
}

Expand All @@ -148,7 +148,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
unsetNodesSelection();

if (!selected) {
addSelectedElements([node]);
addSelectedNodes([node.id]);
}
} else if (!selectNodesOnDrag && !selected && isSelectable) {
unselectNodesAndEdges();
Expand Down Expand Up @@ -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
if (!dragging) {
if (isSelectable && !selectNodesOnDrag && !selected) {
addSelectedElements([node]);
addSelectedNodes([node.id]);
}

onClick?.(event as MouseEvent, node);
Expand Down
8 changes: 1 addition & 7 deletions src/container/EdgeRenderer/index.tsx
Expand Up @@ -88,13 +88,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source);
const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(nodeInternals, edge.target);

if (!sourceIsValid) {
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}`);
if (!sourceIsValid || !targetIsValid) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useResizeHandler.ts
Expand Up @@ -6,7 +6,7 @@ import { ReactFlowState } from '../types';

const updateSizeSelector = (state: ReactFlowState) => state.updateSize;

function useResizeHandler(rendererNode: MutableRefObject<HTMLDivElement | null>) {
function useResizeHandler(rendererNode: MutableRefObject<HTMLDivElement | null>): void {
const updateSize = useStore(updateSizeSelector);

useEffect(() => {
Expand Down
28 changes: 18 additions & 10 deletions src/store/index.ts
Expand Up @@ -27,7 +27,7 @@ import {
XYPosition,
ReactFlowStore,
} 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 { createNodeInternals, createNodeOrEdgeSelectionChange } from './utils';

Expand Down Expand Up @@ -249,28 +249,36 @@ const createStore = () =>

set(stateUpdate);
},
addSelectedElements: (selectedElementsArr: Array<Node | Edge>) => {
const { multiSelectionActive, onNodesChange, onEdgesChange, nodeInternals, edges } = get();
addSelectedNodes: (selectedNodeIds: string[]) => {
const { multiSelectionActive, onNodesChange, nodeInternals } = get();
// @TODO: work with nodeInternals instead of converting it to an array
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
let changedNodes;
let changedEdges;

if (multiSelectionActive) {
changedNodes = selectedElementsArr.filter(isNode).map(createNodeOrEdgeSelectionChange(true));
changedEdges = selectedElementsArr.filter(isEdge).map(createNodeOrEdgeSelectionChange(true));
changedNodes = selectedNodeIds.map(createNodeOrEdgeSelectionChange(true));
} else {
changedNodes = nodes.map((node) =>
createNodeOrEdgeSelectionChange(selectedElementsArr.some((e) => e.id === node.id))(node)
);
changedEdges = edges.map((edge) =>
createNodeOrEdgeSelectionChange(selectedElementsArr.some((e) => e.id === edge.id))(edge)
createNodeOrEdgeSelectionChange(selectedNodeIds.some((nodeId) => nodeId === node.id))(node.id)
);
}

if (changedNodes.length) {
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) {
onEdgesChange?.(changedEdges as EdgeChange[]);
Expand Down
4 changes: 2 additions & 2 deletions src/store/utils.ts
Expand Up @@ -105,8 +105,8 @@ export function createNodeInternals(nodes: Node[], nodeInternals: NodeInternals)
return nextNodeInternals;
}

export const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge) => ({
id: item.id,
export const createNodeOrEdgeSelectionChange = (selected: boolean) => (item: Node | Edge | string) => ({
id: typeof item === 'string' ? item : item.id,
type: 'select',
selected,
});
3 changes: 2 additions & 1 deletion src/types/general.ts
Expand Up @@ -182,7 +182,8 @@ export type ReactFlowActions = {
unsetNodesSelection: () => void;
resetSelectedElements: () => void;
unselectNodesAndEdges: () => void;
addSelectedElements: (elements: Elements) => void;
addSelectedNodes: (nodeIds: string[]) => void;
addSelectedEdges: (edgeIds: string[]) => void;
updateTransform: (transform: Transform) => void;
updateSize: (size: Dimensions) => void;
initD3Zoom: (payload: InitD3ZoomPayload) => void;
Expand Down

0 comments on commit d260abe

Please sign in to comment.