refactor(actions): addSelectedElements => addSelectedNodes, addSelectedEdges
This commit is contained in:
@@ -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,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';
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user