Rename updateEdge to reconnectEdge (#4373)

* refactor(edges): rename update to reconnect

* refactor(react): rename edge update to reconnect

* chore(examples): repair broken reconnect example

* chore(react): changelog
This commit is contained in:
Moritz Klack
2024-06-19 16:57:30 +02:00
committed by GitHub
parent 42f4f59425
commit 75acd24cee
21 changed files with 153 additions and 151 deletions
+4 -4
View File
@@ -34,7 +34,7 @@ import Subflow from '../examples/Subflow';
import SwitchFlow from '../examples/Switch'; import SwitchFlow from '../examples/Switch';
import TouchDevice from '../examples/TouchDevice'; import TouchDevice from '../examples/TouchDevice';
import Undirectional from '../examples/Undirectional'; import Undirectional from '../examples/Undirectional';
import UpdatableEdge from '../examples/UpdatableEdge'; import ReconnectEdge from '../examples/ReconnectEdge';
import UpdateNode from '../examples/UpdateNode'; import UpdateNode from '../examples/UpdateNode';
import UseUpdateNodeInternals from '../examples/UseUpdateNodeInternals'; import UseUpdateNodeInternals from '../examples/UseUpdateNodeInternals';
import UseReactFlow from '../examples/UseReactFlow'; import UseReactFlow from '../examples/UseReactFlow';
@@ -271,9 +271,9 @@ const routes: IRoute[] = [
component: Undirectional, component: Undirectional,
}, },
{ {
name: 'Updatable Edge', name: 'Reconnect Edge',
path: 'updatable-edge', path: 'reconnect-edge',
component: UpdatableEdge, component: ReconnectEdge,
}, },
{ {
name: 'Update Node', name: 'Update Node',
@@ -2,7 +2,7 @@ import { useState, useCallback, MouseEvent as ReactMouseEvent } from 'react';
import { import {
ReactFlow, ReactFlow,
Controls, Controls,
updateEdge, reconnectEdge,
addEdge, addEdge,
applyNodeChanges, applyNodeChanges,
applyEdgeChanges, applyEdgeChanges,
@@ -91,21 +91,21 @@ const initialNodes: Node[] = [
]; ];
const initialEdges: Edge[] = [ const initialEdges: Edge[] = [
{ id: 'e1-3', source: '1', target: '3', label: 'This edge can only be updated from source', updatable: 'source' }, { id: 'e1-3', source: '1', target: '3', label: 'This edge can only be updated from source', reconnectable: 'source' },
{ id: 'e2-4', source: '2', target: '4', label: 'This edge can only be updated from target', updatable: 'target' }, { id: 'e2-4', source: '2', target: '4', label: 'This edge can only be updated from target', reconnectable: 'target' },
{ id: 'e5-6', source: '5', target: '6', label: 'This edge can be updated from both sides' }, { id: 'e5-6', source: '5', target: '6', label: 'This edge can be updated from both sides' },
]; ];
const onEdgeUpdateStart = (_: ReactMouseEvent, edge: Edge, handleType: HandleType) => const onReconnectStart = (_: ReactMouseEvent, edge: Edge, handleType: HandleType) =>
console.log(`start update ${handleType} handle`, edge); console.log(`start update ${handleType} handle`, edge);
const onEdgeUpdateEnd = (_: MouseEvent | TouchEvent, edge: Edge, handleType: HandleType) => const onReconnectEnd = (_: MouseEvent | TouchEvent, edge: Edge, handleType: HandleType) =>
console.log(`end update ${handleType} handle`, edge); console.log(`end update ${handleType} handle`, edge);
const UpdatableEdge = () => { const ReconnectEdge = () => {
const [nodes, setNodes] = useState<Node[]>(initialNodes); const [nodes, setNodes] = useState<Node[]>(initialNodes);
const [edges, setEdges] = useState<Edge[]>(initialEdges); const [edges, setEdges] = useState<Edge[]>(initialEdges);
const onEdgeUpdate = (oldEdge: Edge, newConnection: Connection) => const onReconnect = (oldEdge: Edge, newConnection: Connection) =>
setEdges((els) => updateEdge(oldEdge, newConnection, els)); setEdges((els) => reconnectEdge(oldEdge, newConnection, els));
const onConnect = (connection: Connection) => setEdges((els) => addEdge(connection, els)); const onConnect = (connection: Connection) => setEdges((els) => addEdge(connection, els));
const onNodesChange = useCallback((changes: NodeChange[]) => { const onNodesChange = useCallback((changes: NodeChange[]) => {
@@ -123,10 +123,10 @@ const UpdatableEdge = () => {
onNodesChange={onNodesChange} onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange} onEdgesChange={onEdgesChange}
snapToGrid={true} snapToGrid={true}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
onConnect={onConnect} onConnect={onConnect}
onEdgeUpdateStart={onEdgeUpdateStart} onReconnectStart={onReconnectStart}
onEdgeUpdateEnd={onEdgeUpdateEnd} onReconnectEnd={onReconnectEnd}
fitView fitView
> >
<Controls /> <Controls />
@@ -134,4 +134,4 @@ const UpdatableEdge = () => {
); );
}; };
export default UpdatableEdge; export default ReconnectEdge;
@@ -10,7 +10,7 @@ import {
Edge, Edge,
ConnectionLineType, ConnectionLineType,
ConnectionMode, ConnectionMode,
updateEdge, reconnectEdge,
useNodesState, useNodesState,
useEdgesState, useEdgesState,
} from '@xyflow/react'; } from '@xyflow/react';
@@ -22,55 +22,55 @@ const initialNodes: Node[] = [
id: '00', id: '00',
type: 'custom', type: 'custom',
position: { x: 300, y: 250 }, position: { x: 300, y: 250 },
data: null, data: {},
}, },
{ {
id: '01', id: '01',
type: 'custom', type: 'custom',
position: { x: 100, y: 50 }, position: { x: 100, y: 50 },
data: null, data: {},
}, },
{ {
id: '02', id: '02',
type: 'custom', type: 'custom',
position: { x: 500, y: 50 }, position: { x: 500, y: 50 },
data: null, data: {},
}, },
{ {
id: '03', id: '03',
type: 'custom', type: 'custom',
position: { x: 500, y: 500 }, position: { x: 500, y: 500 },
data: null, data: {},
}, },
{ {
id: '04', id: '04',
type: 'custom', type: 'custom',
position: { x: 100, y: 500 }, position: { x: 100, y: 500 },
data: null, data: {},
}, },
{ {
id: '10', id: '10',
type: 'custom', type: 'custom',
position: { x: 300, y: 5 }, position: { x: 300, y: 5 },
data: null, data: {},
}, },
{ {
id: '20', id: '20',
type: 'custom', type: 'custom',
position: { x: 600, y: 250 }, position: { x: 600, y: 250 },
data: null, data: {},
}, },
{ {
id: '30', id: '30',
type: 'custom', type: 'custom',
position: { x: 300, y: 600 }, position: { x: 300, y: 600 },
data: null, data: {},
}, },
{ {
id: '40', id: '40',
type: 'custom', type: 'custom',
position: { x: 5, y: 250 }, position: { x: 5, y: 250 },
data: null, data: {},
}, },
]; ];
@@ -186,8 +186,8 @@ const UpdateNodeInternalsFlow = () => {
const { screenToFlowPosition } = useReactFlow(); const { screenToFlowPosition } = useReactFlow();
const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]); const onConnect = useCallback((params: Edge | Connection) => setEdges((els) => addEdge(params, els)), [setEdges]);
const onEdgeUpdate = useCallback( const onReconnect = useCallback(
(oldEdge: Edge, newConnection: Connection) => setEdges((els) => updateEdge(oldEdge, newConnection, els)), (oldEdge: Edge, newConnection: Connection) => setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),
[] []
); );
@@ -215,7 +215,7 @@ const UpdateNodeInternalsFlow = () => {
onPaneClick={onPaneClick} onPaneClick={onPaneClick}
connectionLineType={ConnectionLineType.Bezier} connectionLineType={ConnectionLineType.Bezier}
connectionMode={ConnectionMode.Loose} connectionMode={ConnectionMode.Loose}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
/> />
); );
}; };
@@ -13,7 +13,7 @@ import {
OnConnectStart, OnConnectStart,
OnConnectEnd, OnConnectEnd,
OnConnect, OnConnect,
updateEdge, reconnectEdge,
Edge, Edge,
IsValidConnection, IsValidConnection,
OnBeforeDelete, OnBeforeDelete,
@@ -24,10 +24,10 @@ import ConnectionStatus from './ConnectionStatus';
import styles from './validation.module.css'; import styles from './validation.module.css';
const initialNodes: Node[] = [ const initialNodes: Node[] = [
{ id: '0', type: 'custominput', position: { x: 0, y: 150 }, data: null }, { id: '0', type: 'custominput', position: { x: 0, y: 150 }, data: {} },
{ id: 'A', type: 'customnode', position: { x: 250, y: 0 }, data: null }, { id: 'A', type: 'customnode', position: { x: 250, y: 0 }, data: {} },
{ id: 'B', type: 'customnode', position: { x: 250, y: 150 }, data: null }, { id: 'B', type: 'customnode', position: { x: 250, y: 150 }, data: {} },
{ id: 'C', type: 'customnode', position: { x: 250, y: 300 }, data: null }, { id: 'C', type: 'customnode', position: { x: 250, y: 300 }, data: {} },
]; ];
const isValidConnection: IsValidConnection = (connection) => connection.target === 'B'; const isValidConnection: IsValidConnection = (connection) => connection.target === 'B';
@@ -81,8 +81,8 @@ const ValidationFlow = () => {
[value] [value]
); );
const onEdgeUpdate = useCallback( const onReconnect = useCallback(
(oldEdge: Edge, newConnection: Connection) => setEdges((els) => updateEdge(oldEdge, newConnection, els)), (oldEdge: Edge, newConnection: Connection) => setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),
[setEdges] [setEdges]
); );
@@ -102,7 +102,7 @@ const ValidationFlow = () => {
nodeTypes={nodeTypes} nodeTypes={nodeTypes}
onConnectStart={onConnectStart} onConnectStart={onConnectStart}
onConnectEnd={onConnectEnd} onConnectEnd={onConnectEnd}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
isValidConnection={isValidConnection} isValidConnection={isValidConnection}
onBeforeDelete={onBeforeDelete} onBeforeDelete={onBeforeDelete}
fitView fitView
@@ -149,7 +149,7 @@ export default {
// source: '9', // source: '9',
// target: '11', // target: '11',
// label: 'focusable', // label: 'focusable',
// updatable: true // reconnectable: true
// }, // },
// { // {
// id: 'not-focusable', // id: 'not-focusable',
@@ -146,7 +146,7 @@ export default {
// source: '9', // source: '9',
// target: '11', // target: '11',
// label: 'focusable', // label: 'focusable',
// updatable: true // reconnectable: true
// }, // },
// { // {
// id: 'not-focusable', // id: 'not-focusable',
+5
View File
@@ -1,5 +1,10 @@
# @xyflow/react # @xyflow/react
## 12.0.0-next.22
- ⚠️ rename `updateEdge` to `reconnectEdge` and realted APIs [#4373](https://github.com/xyflow/xyflow/pull/4373)
## 12.0.0-next.21 ## 12.0.0-next.21
- fix node origin bug - fix node origin bug
@@ -1,4 +1,4 @@
// Updatable edges have a anchors around their handles to update the edge. // Reconnectable edges have a anchors around their handles to reconnect the edge.
import { XYHandle, type Connection, EdgePosition } from '@xyflow/system'; import { XYHandle, type Connection, EdgePosition } from '@xyflow/system';
import { EdgeAnchor } from '../Edges/EdgeAnchor'; import { EdgeAnchor } from '../Edges/EdgeAnchor';
@@ -7,20 +7,20 @@ import { useStoreApi } from '../../hooks/useStore';
type EdgeUpdateAnchorsProps<EdgeType extends Edge = Edge> = { type EdgeUpdateAnchorsProps<EdgeType extends Edge = Edge> = {
edge: EdgeType; edge: EdgeType;
isUpdatable: boolean | 'source' | 'target'; isReconnectable: boolean | 'source' | 'target';
edgeUpdaterRadius: EdgeWrapperProps['edgeUpdaterRadius']; reconnectRadius: EdgeWrapperProps['reconnectRadius'];
sourceHandleId: Edge['sourceHandle']; sourceHandleId: Edge['sourceHandle'];
targetHandleId: Edge['targetHandle']; targetHandleId: Edge['targetHandle'];
onEdgeUpdate: EdgeWrapperProps<EdgeType>['onEdgeUpdate']; onReconnect: EdgeWrapperProps<EdgeType>['onReconnect'];
onEdgeUpdateStart: EdgeWrapperProps<EdgeType>['onEdgeUpdateStart']; onReconnectStart: EdgeWrapperProps<EdgeType>['onReconnectStart'];
onEdgeUpdateEnd: EdgeWrapperProps<EdgeType>['onEdgeUpdateEnd']; onReconnectEnd: EdgeWrapperProps<EdgeType>['onReconnectEnd'];
setUpdateHover: (hover: boolean) => void; setUpdateHover: (hover: boolean) => void;
setUpdating: (updating: boolean) => void; setReconnecting: (updating: boolean) => void;
} & EdgePosition; } & EdgePosition;
export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({ export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
isUpdatable, isReconnectable,
edgeUpdaterRadius, reconnectRadius,
edge, edge,
targetHandleId, targetHandleId,
sourceHandleId, sourceHandleId,
@@ -30,10 +30,10 @@ export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
targetY, targetY,
sourcePosition, sourcePosition,
targetPosition, targetPosition,
onEdgeUpdate, onReconnect,
onEdgeUpdateStart, onReconnectStart,
onEdgeUpdateEnd, onReconnectEnd,
setUpdating, setReconnecting,
setUpdateHover, setUpdateHover,
}: EdgeUpdateAnchorsProps<EdgeType>) { }: EdgeUpdateAnchorsProps<EdgeType>) {
const store = useStoreApi(); const store = useStoreApi();
@@ -65,15 +65,15 @@ export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
const isTarget = isSourceHandle; const isTarget = isSourceHandle;
setUpdating(true); setReconnecting(true);
onEdgeUpdateStart?.(event, edge, handleType); onReconnectStart?.(event, edge, handleType);
const _onEdgeUpdateEnd = (evt: MouseEvent | TouchEvent) => { const _onReconnectEnd = (evt: MouseEvent | TouchEvent) => {
setUpdating(false); setReconnecting(false);
onEdgeUpdateEnd?.(evt, edge, handleType); onReconnectEnd?.(evt, edge, handleType);
}; };
const onConnectEdge = (connection: Connection) => onEdgeUpdate?.(edge, connection); const onConnectEdge = (connection: Connection) => onReconnect?.(edge, connection);
XYHandle.onPointerDown(event.nativeEvent, { XYHandle.onPointerDown(event.nativeEvent, {
autoPanOnConnect, autoPanOnConnect,
@@ -93,43 +93,43 @@ export function EdgeUpdateAnchors<EdgeType extends Edge = Edge>({
onConnect: onConnectEdge, onConnect: onConnectEdge,
onConnectStart, onConnectStart,
onConnectEnd, onConnectEnd,
onEdgeUpdateEnd: _onEdgeUpdateEnd, onReconnectEnd: _onReconnectEnd,
updateConnection, updateConnection,
getTransform: () => store.getState().transform, getTransform: () => store.getState().transform,
getConnectionStartHandle: () => store.getState().connectionStartHandle, getConnectionStartHandle: () => store.getState().connectionStartHandle,
}); });
}; };
const onEdgeUpdaterSourceMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void => const onReconnectSourceMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
handleEdgeUpdater(event, true); handleEdgeUpdater(event, true);
const onEdgeUpdaterTargetMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void => const onReconnectTargetMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
handleEdgeUpdater(event, false); handleEdgeUpdater(event, false);
const onEdgeUpdaterMouseEnter = () => setUpdateHover(true); const onReconnectMouseEnter = () => setUpdateHover(true);
const onEdgeUpdaterMouseOut = () => setUpdateHover(false); const onReconnectMouseOut = () => setUpdateHover(false);
return ( return (
<> <>
{(isUpdatable === 'source' || isUpdatable === true) && ( {(isReconnectable === 'source' || isReconnectable === true) && (
<EdgeAnchor <EdgeAnchor
position={sourcePosition} position={sourcePosition}
centerX={sourceX} centerX={sourceX}
centerY={sourceY} centerY={sourceY}
radius={edgeUpdaterRadius} radius={reconnectRadius}
onMouseDown={onEdgeUpdaterSourceMouseDown} onMouseDown={onReconnectSourceMouseDown}
onMouseEnter={onEdgeUpdaterMouseEnter} onMouseEnter={onReconnectMouseEnter}
onMouseOut={onEdgeUpdaterMouseOut} onMouseOut={onReconnectMouseOut}
type="source" type="source"
/> />
)} )}
{(isUpdatable === 'target' || isUpdatable === true) && ( {(isReconnectable === 'target' || isReconnectable === true) && (
<EdgeAnchor <EdgeAnchor
position={targetPosition} position={targetPosition}
centerX={targetX} centerX={targetX}
centerY={targetY} centerY={targetY}
radius={edgeUpdaterRadius} radius={reconnectRadius}
onMouseDown={onEdgeUpdaterTargetMouseDown} onMouseDown={onReconnectTargetMouseDown}
onMouseEnter={onEdgeUpdaterMouseEnter} onMouseEnter={onReconnectMouseEnter}
onMouseOut={onEdgeUpdaterMouseOut} onMouseOut={onReconnectMouseOut}
type="target" type="target"
/> />
)} )}
@@ -18,7 +18,7 @@ import type { Edge, EdgeWrapperProps } from '../../types';
export function EdgeWrapper<EdgeType extends Edge = Edge>({ export function EdgeWrapper<EdgeType extends Edge = Edge>({
id, id,
edgesFocusable, edgesFocusable,
edgesUpdatable, edgesReconnectable,
elementsSelectable, elementsSelectable,
onClick, onClick,
onDoubleClick, onDoubleClick,
@@ -26,10 +26,10 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
onMouseEnter, onMouseEnter,
onMouseMove, onMouseMove,
onMouseLeave, onMouseLeave,
edgeUpdaterRadius, reconnectRadius,
onEdgeUpdate, onReconnect,
onEdgeUpdateStart, onReconnectStart,
onEdgeUpdateEnd, onReconnectEnd,
rfId, rfId,
edgeTypes, edgeTypes,
noPanClassName, noPanClassName,
@@ -50,14 +50,14 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
} }
const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined')); const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined'));
const isUpdatable = const isReconnectable =
typeof onEdgeUpdate !== 'undefined' && typeof onReconnect !== 'undefined' &&
(edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined')); (edge.reconnectable || (edgesReconnectable && typeof edge.reconnectable === 'undefined'));
const isSelectable = !!(edge.selectable || (elementsSelectable && typeof edge.selectable === 'undefined')); const isSelectable = !!(edge.selectable || (elementsSelectable && typeof edge.selectable === 'undefined'));
const edgeRef = useRef<SVGGElement>(null); const edgeRef = useRef<SVGGElement>(null);
const [updateHover, setUpdateHover] = useState<boolean>(false); const [updateHover, setUpdateHover] = useState<boolean>(false);
const [updating, setUpdating] = useState<boolean>(false); const [reconnecting, setReconnecting] = useState<boolean>(false);
const store = useStoreApi(); const store = useStoreApi();
const { zIndex, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = useStore( const { zIndex, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = useStore(
@@ -207,7 +207,7 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
aria-describedby={isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined} aria-describedby={isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined}
ref={edgeRef} ref={edgeRef}
> >
{!updating && ( {!reconnecting && (
<EdgeComponent <EdgeComponent
id={id} id={id}
source={edge.source} source={edge.source}
@@ -239,14 +239,14 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
interactionWidth={edge.interactionWidth} interactionWidth={edge.interactionWidth}
/> />
)} )}
{isUpdatable && ( {isReconnectable && (
<EdgeUpdateAnchors<EdgeType> <EdgeUpdateAnchors<EdgeType>
edge={edge} edge={edge}
isUpdatable={isUpdatable} isReconnectable={isReconnectable}
edgeUpdaterRadius={edgeUpdaterRadius} reconnectRadius={reconnectRadius}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
onEdgeUpdateStart={onEdgeUpdateStart} onReconnectStart={onReconnectStart}
onEdgeUpdateEnd={onEdgeUpdateEnd} onReconnectEnd={onReconnectEnd}
sourceX={sourceX} sourceX={sourceX}
sourceY={sourceY} sourceY={sourceY}
targetX={targetX} targetX={targetX}
@@ -254,7 +254,7 @@ export function EdgeWrapper<EdgeType extends Edge = Edge>({
sourcePosition={sourcePosition} sourcePosition={sourcePosition}
targetPosition={targetPosition} targetPosition={targetPosition}
setUpdateHover={setUpdateHover} setUpdateHover={setUpdateHover}
setUpdating={setUpdating} setReconnecting={setReconnecting}
sourceHandleId={edge.sourceHandle} sourceHandleId={edge.sourceHandle}
targetHandleId={edge.targetHandle} targetHandleId={edge.targetHandle}
/> />
@@ -26,7 +26,7 @@ const reactFlowFieldsToTrack = [
'nodesConnectable', 'nodesConnectable',
'nodesFocusable', 'nodesFocusable',
'edgesFocusable', 'edgesFocusable',
'edgesUpdatable', 'edgesReconnectable',
'elevateNodesOnSelect', 'elevateNodesOnSelect',
'elevateEdgesOnSelect', 'elevateEdgesOnSelect',
'minZoom', 'minZoom',
@@ -14,14 +14,14 @@ type EdgeRendererProps<EdgeType extends Edge = Edge> = Pick<
| 'onEdgeDoubleClick' | 'onEdgeDoubleClick'
| 'defaultMarkerColor' | 'defaultMarkerColor'
| 'onlyRenderVisibleElements' | 'onlyRenderVisibleElements'
| 'onEdgeUpdate' | 'onReconnect'
| 'onEdgeContextMenu' | 'onEdgeContextMenu'
| 'onEdgeMouseEnter' | 'onEdgeMouseEnter'
| 'onEdgeMouseMove' | 'onEdgeMouseMove'
| 'onEdgeMouseLeave' | 'onEdgeMouseLeave'
| 'onEdgeUpdateStart' | 'onReconnectStart'
| 'onEdgeUpdateEnd' | 'onReconnectEnd'
| 'edgeUpdaterRadius' | 'reconnectRadius'
| 'noPanClassName' | 'noPanClassName'
| 'rfId' | 'rfId'
| 'disableKeyboardA11y' | 'disableKeyboardA11y'
@@ -34,7 +34,7 @@ const selector = (s: ReactFlowState) => ({
width: s.width, width: s.width,
height: s.height, height: s.height,
edgesFocusable: s.edgesFocusable, edgesFocusable: s.edgesFocusable,
edgesUpdatable: s.edgesUpdatable, edgesReconnectable: s.edgesReconnectable,
elementsSelectable: s.elementsSelectable, elementsSelectable: s.elementsSelectable,
connectionMode: s.connectionMode, connectionMode: s.connectionMode,
onError: s.onError, onError: s.onError,
@@ -46,19 +46,19 @@ function EdgeRendererComponent<EdgeType extends Edge = Edge>({
rfId, rfId,
edgeTypes, edgeTypes,
noPanClassName, noPanClassName,
onEdgeUpdate, onReconnect,
onEdgeContextMenu, onEdgeContextMenu,
onEdgeMouseEnter, onEdgeMouseEnter,
onEdgeMouseMove, onEdgeMouseMove,
onEdgeMouseLeave, onEdgeMouseLeave,
onEdgeClick, onEdgeClick,
edgeUpdaterRadius, reconnectRadius,
onEdgeDoubleClick, onEdgeDoubleClick,
onEdgeUpdateStart, onReconnectStart,
onEdgeUpdateEnd, onReconnectEnd,
disableKeyboardA11y, disableKeyboardA11y,
}: EdgeRendererProps<EdgeType>) { }: EdgeRendererProps<EdgeType>) {
const { edgesFocusable, edgesUpdatable, elementsSelectable, onError } = useStore(selector, shallow); const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector, shallow);
const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements); const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
return ( return (
@@ -71,19 +71,19 @@ function EdgeRendererComponent<EdgeType extends Edge = Edge>({
key={id} key={id}
id={id} id={id}
edgesFocusable={edgesFocusable} edgesFocusable={edgesFocusable}
edgesUpdatable={edgesUpdatable} edgesReconnectable={edgesReconnectable}
elementsSelectable={elementsSelectable} elementsSelectable={elementsSelectable}
noPanClassName={noPanClassName} noPanClassName={noPanClassName}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
onContextMenu={onEdgeContextMenu} onContextMenu={onEdgeContextMenu}
onMouseEnter={onEdgeMouseEnter} onMouseEnter={onEdgeMouseEnter}
onMouseMove={onEdgeMouseMove} onMouseMove={onEdgeMouseMove}
onMouseLeave={onEdgeMouseLeave} onMouseLeave={onEdgeMouseLeave}
onClick={onEdgeClick} onClick={onEdgeClick}
edgeUpdaterRadius={edgeUpdaterRadius} reconnectRadius={reconnectRadius}
onDoubleClick={onEdgeDoubleClick} onDoubleClick={onEdgeDoubleClick}
onEdgeUpdateStart={onEdgeUpdateStart} onReconnectStart={onReconnectStart}
onEdgeUpdateEnd={onEdgeUpdateEnd} onReconnectEnd={onReconnectEnd}
rfId={rfId} rfId={rfId}
onError={onError} onError={onError}
edgeTypes={edgeTypes} edgeTypes={edgeTypes}
@@ -85,14 +85,14 @@ function GraphViewComponent<NodeType extends Node = Node, EdgeType extends Edge
onPaneMouseLeave, onPaneMouseLeave,
onPaneScroll, onPaneScroll,
onPaneContextMenu, onPaneContextMenu,
onEdgeUpdate,
onEdgeContextMenu, onEdgeContextMenu,
onEdgeMouseEnter, onEdgeMouseEnter,
onEdgeMouseMove, onEdgeMouseMove,
onEdgeMouseLeave, onEdgeMouseLeave,
edgeUpdaterRadius, reconnectRadius,
onEdgeUpdateStart, onReconnect,
onEdgeUpdateEnd, onReconnectStart,
onReconnectEnd,
noDragClassName, noDragClassName,
noWheelClassName, noWheelClassName,
noPanClassName, noPanClassName,
@@ -153,15 +153,15 @@ function GraphViewComponent<NodeType extends Node = Node, EdgeType extends Edge
edgeTypes={edgeTypes} edgeTypes={edgeTypes}
onEdgeClick={onEdgeClick} onEdgeClick={onEdgeClick}
onEdgeDoubleClick={onEdgeDoubleClick} onEdgeDoubleClick={onEdgeDoubleClick}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
onReconnectStart={onReconnectStart}
onReconnectEnd={onReconnectEnd}
onlyRenderVisibleElements={onlyRenderVisibleElements} onlyRenderVisibleElements={onlyRenderVisibleElements}
onEdgeContextMenu={onEdgeContextMenu} onEdgeContextMenu={onEdgeContextMenu}
onEdgeMouseEnter={onEdgeMouseEnter} onEdgeMouseEnter={onEdgeMouseEnter}
onEdgeMouseMove={onEdgeMouseMove} onEdgeMouseMove={onEdgeMouseMove}
onEdgeMouseLeave={onEdgeMouseLeave} onEdgeMouseLeave={onEdgeMouseLeave}
onEdgeUpdateStart={onEdgeUpdateStart} reconnectRadius={reconnectRadius}
onEdgeUpdateEnd={onEdgeUpdateEnd}
edgeUpdaterRadius={edgeUpdaterRadius}
defaultMarkerColor={defaultMarkerColor} defaultMarkerColor={defaultMarkerColor}
noPanClassName={noPanClassName} noPanClassName={noPanClassName}
disableKeyboardA11y={disableKeyboardA11y} disableKeyboardA11y={disableKeyboardA11y}
@@ -81,7 +81,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
nodesFocusable, nodesFocusable,
nodeOrigin = defaultNodeOrigin, nodeOrigin = defaultNodeOrigin,
edgesFocusable, edgesFocusable,
edgesUpdatable, edgesReconnectable,
elementsSelectable = true, elementsSelectable = true,
defaultViewport = initViewport, defaultViewport = initViewport,
minZoom = 0.5, minZoom = 0.5,
@@ -104,15 +104,15 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
onPaneScroll, onPaneScroll,
onPaneContextMenu, onPaneContextMenu,
children, children,
onEdgeUpdate, onReconnect,
onReconnectStart,
onReconnectEnd,
onEdgeContextMenu, onEdgeContextMenu,
onEdgeDoubleClick, onEdgeDoubleClick,
onEdgeMouseEnter, onEdgeMouseEnter,
onEdgeMouseMove, onEdgeMouseMove,
onEdgeMouseLeave, onEdgeMouseLeave,
onEdgeUpdateStart, reconnectRadius = 10,
onEdgeUpdateEnd,
edgeUpdaterRadius = 10,
onNodesChange, onNodesChange,
onEdgesChange, onEdgesChange,
noDragClassName = 'nodrag', noDragClassName = 'nodrag',
@@ -202,15 +202,15 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
onSelectionContextMenu={onSelectionContextMenu} onSelectionContextMenu={onSelectionContextMenu}
onSelectionStart={onSelectionStart} onSelectionStart={onSelectionStart}
onSelectionEnd={onSelectionEnd} onSelectionEnd={onSelectionEnd}
onEdgeUpdate={onEdgeUpdate} onReconnect={onReconnect}
onReconnectStart={onReconnectStart}
onReconnectEnd={onReconnectEnd}
onEdgeContextMenu={onEdgeContextMenu} onEdgeContextMenu={onEdgeContextMenu}
onEdgeDoubleClick={onEdgeDoubleClick} onEdgeDoubleClick={onEdgeDoubleClick}
onEdgeMouseEnter={onEdgeMouseEnter} onEdgeMouseEnter={onEdgeMouseEnter}
onEdgeMouseMove={onEdgeMouseMove} onEdgeMouseMove={onEdgeMouseMove}
onEdgeMouseLeave={onEdgeMouseLeave} onEdgeMouseLeave={onEdgeMouseLeave}
onEdgeUpdateStart={onEdgeUpdateStart} reconnectRadius={reconnectRadius}
onEdgeUpdateEnd={onEdgeUpdateEnd}
edgeUpdaterRadius={edgeUpdaterRadius}
defaultMarkerColor={defaultMarkerColor} defaultMarkerColor={defaultMarkerColor}
noDragClassName={noDragClassName} noDragClassName={noDragClassName}
noWheelClassName={noWheelClassName} noWheelClassName={noWheelClassName}
@@ -236,7 +236,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
nodesConnectable={nodesConnectable} nodesConnectable={nodesConnectable}
nodesFocusable={nodesFocusable} nodesFocusable={nodesFocusable}
edgesFocusable={edgesFocusable} edgesFocusable={edgesFocusable}
edgesUpdatable={edgesUpdatable} edgesReconnectable={edgesReconnectable}
elementsSelectable={elementsSelectable} elementsSelectable={elementsSelectable}
elevateNodesOnSelect={elevateNodesOnSelect} elevateNodesOnSelect={elevateNodesOnSelect}
elevateEdgesOnSelect={elevateEdgesOnSelect} elevateEdgesOnSelect={elevateEdgesOnSelect}
+1 -1
View File
@@ -116,6 +116,6 @@ export {
getIncomers, getIncomers,
getOutgoers, getOutgoers,
addEdge, addEdge,
updateEdge, reconnectEdge,
getConnectedEdges, getConnectedEdges,
} from '@xyflow/system'; } from '@xyflow/system';
+1 -1
View File
@@ -92,7 +92,7 @@ const getInitialState = ({
nodesConnectable: true, nodesConnectable: true,
nodesFocusable: true, nodesFocusable: true,
edgesFocusable: true, edgesFocusable: true,
edgesUpdatable: true, edgesReconnectable: true,
elementsSelectable: true, elementsSelectable: true,
elevateNodesOnSelect: true, elevateNodesOnSelect: true,
elevateEdgesOnSelect: false, elevateEdgesOnSelect: false,
+6 -6
View File
@@ -29,7 +29,7 @@ import type {
Node, Node,
Edge, Edge,
ConnectionLineComponent, ConnectionLineComponent,
OnEdgeUpdateFunc, OnReconnect,
OnInit, OnInit,
DefaultEdgeOptions, DefaultEdgeOptions,
FitViewOptions, FitViewOptions,
@@ -129,9 +129,9 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
onEdgeMouseLeave?: EdgeMouseHandler<EdgeType>; onEdgeMouseLeave?: EdgeMouseHandler<EdgeType>;
/** This event handler is called when a user double clicks on an edge */ /** This event handler is called when a user double clicks on an edge */
onEdgeDoubleClick?: EdgeMouseHandler<EdgeType>; onEdgeDoubleClick?: EdgeMouseHandler<EdgeType>;
onEdgeUpdateStart?: (event: ReactMouseEvent, edge: EdgeType, handleType: HandleType) => void; onReconnect?: OnReconnect<EdgeType>;
onEdgeUpdateEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void; onReconnectStart?: (event: ReactMouseEvent, edge: EdgeType, handleType: HandleType) => void;
onEdgeUpdate?: OnEdgeUpdateFunc<EdgeType>; onReconnectEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void;
/** This event handler is called when a Node is updated /** This event handler is called when a Node is updated
* @example // Use NodesState hook to create edges and get onNodesChange handler * @example // Use NodesState hook to create edges and get onNodesChange handler
* import ReactFlow, { useNodesState } from '@xyflow/react'; * import ReactFlow, { useNodesState } from '@xyflow/react';
@@ -330,7 +330,7 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
/** Controls if all edges should be updateable /** Controls if all edges should be updateable
* @default true * @default true
*/ */
edgesUpdatable?: boolean; edgesReconnectable?: boolean;
/** Controls if all elements should (nodes & edges) be selectable /** Controls if all elements should (nodes & edges) be selectable
* @default true * @default true
*/ */
@@ -413,7 +413,7 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
panOnScrollMode?: PanOnScrollMode; panOnScrollMode?: PanOnScrollMode;
/** Controls if the viewport should zoom by double clicking somewhere on the flow */ /** Controls if the viewport should zoom by double clicking somewhere on the flow */
zoomOnDoubleClick?: boolean; zoomOnDoubleClick?: boolean;
edgeUpdaterRadius?: number; reconnectRadius?: number;
noDragClassName?: string; noDragClassName?: string;
noWheelClassName?: string; noWheelClassName?: string;
noPanClassName?: string; noPanClassName?: string;
+7 -9
View File
@@ -28,8 +28,6 @@ export type EdgeLabelOptions = {
labelBgBorderRadius?: number; labelBgBorderRadius?: number;
}; };
export type EdgeUpdatable = boolean | HandleType;
/** /**
* The Edge type is mainly used for the `edges` that get passed to the ReactFlow component * The Edge type is mainly used for the `edges` that get passed to the ReactFlow component
* @public * @public
@@ -41,7 +39,7 @@ export type Edge<
EdgeLabelOptions & { EdgeLabelOptions & {
style?: CSSProperties; style?: CSSProperties;
className?: string; className?: string;
updatable?: EdgeUpdatable; reconnectable?: boolean | HandleType;
focusable?: boolean; focusable?: boolean;
}; };
@@ -69,19 +67,19 @@ export type EdgeMouseHandler<EdgeType extends Edge = Edge> = (event: ReactMouseE
export type EdgeWrapperProps<EdgeType extends Edge = Edge> = { export type EdgeWrapperProps<EdgeType extends Edge = Edge> = {
id: string; id: string;
edgesFocusable: boolean; edgesFocusable: boolean;
edgesUpdatable: boolean; edgesReconnectable: boolean;
elementsSelectable: boolean; elementsSelectable: boolean;
noPanClassName: string; noPanClassName: string;
onClick?: EdgeMouseHandler<EdgeType>; onClick?: EdgeMouseHandler<EdgeType>;
onDoubleClick?: EdgeMouseHandler<EdgeType>; onDoubleClick?: EdgeMouseHandler<EdgeType>;
onEdgeUpdate?: OnEdgeUpdateFunc<EdgeType>; onReconnect?: OnReconnect<EdgeType>;
onContextMenu?: EdgeMouseHandler<EdgeType>; onContextMenu?: EdgeMouseHandler<EdgeType>;
onMouseEnter?: EdgeMouseHandler<EdgeType>; onMouseEnter?: EdgeMouseHandler<EdgeType>;
onMouseMove?: EdgeMouseHandler<EdgeType>; onMouseMove?: EdgeMouseHandler<EdgeType>;
onMouseLeave?: EdgeMouseHandler<EdgeType>; onMouseLeave?: EdgeMouseHandler<EdgeType>;
edgeUpdaterRadius?: number; reconnectRadius?: number;
onEdgeUpdateStart?: (event: ReactMouseEvent, edge: EdgeType, handleType: HandleType) => void; onReconnectStart?: (event: ReactMouseEvent, edge: EdgeType, handleType: HandleType) => void;
onEdgeUpdateEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void; onReconnectEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void;
rfId?: string; rfId?: string;
edgeTypes?: EdgeTypes; edgeTypes?: EdgeTypes;
onError?: OnError; onError?: OnError;
@@ -191,7 +189,7 @@ export type StraightEdgeProps = Omit<EdgeComponentProps, 'sourcePosition' | 'tar
*/ */
export type SimpleBezierEdgeProps = EdgeComponentProps; export type SimpleBezierEdgeProps = EdgeComponentProps;
export type OnEdgeUpdateFunc<EdgeType extends Edge = Edge> = (oldEdge: EdgeType, newConnection: Connection) => void; export type OnReconnect<EdgeType extends Edge = Edge> = (oldEdge: EdgeType, newConnection: Connection) => void;
export type ConnectionLineComponentProps = { export type ConnectionLineComponentProps = {
connectionLineStyle?: CSSProperties; connectionLineStyle?: CSSProperties;
+1 -1
View File
@@ -89,7 +89,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
nodesConnectable: boolean; nodesConnectable: boolean;
nodesFocusable: boolean; nodesFocusable: boolean;
edgesFocusable: boolean; edgesFocusable: boolean;
edgesUpdatable: boolean; edgesReconnectable: boolean;
elementsSelectable: boolean; elementsSelectable: boolean;
elevateNodesOnSelect: boolean; elevateNodesOnSelect: boolean;
elevateEdgesOnSelect: boolean; elevateEdgesOnSelect: boolean;
+1 -2
View File
@@ -124,6 +124,5 @@ export {
getIncomers, getIncomers,
getOutgoers, getOutgoers,
getConnectedEdges, getConnectedEdges,
addEdge, addEdge
updateEdge
} from '@xyflow/system'; } from '@xyflow/system';
+4 -4
View File
@@ -132,23 +132,23 @@ export const addEdge = <EdgeType extends EdgeBase>(
return edges.concat(edge); return edges.concat(edge);
}; };
export type UpdateEdgeOptions = { export type ReconnectEdgeOptions = {
shouldReplaceId?: boolean; shouldReplaceId?: boolean;
}; };
/** /**
* A handy utility to update an existing Edge with new properties * A handy utility to reconnect an existing edge with new properties
* @param oldEdge - The edge you want to update * @param oldEdge - The edge you want to update
* @param newConnection - The new connection you want to update the edge with * @param newConnection - The new connection you want to update the edge with
* @param edges - The array of all current edges * @param edges - The array of all current edges
* @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id
* @returns the updated edges array * @returns the updated edges array
*/ */
export const updateEdge = <EdgeType extends EdgeBase>( export const reconnectEdge = <EdgeType extends EdgeBase>(
oldEdge: EdgeType, oldEdge: EdgeType,
newConnection: Connection, newConnection: Connection,
edges: EdgeType[], edges: EdgeType[],
options: UpdateEdgeOptions = { shouldReplaceId: true } options: ReconnectEdgeOptions = { shouldReplaceId: true }
): EdgeType[] => { ): EdgeType[] => {
const { id: oldEdgeId, ...rest } = oldEdge; const { id: oldEdgeId, ...rest } = oldEdge;
+3 -3
View File
@@ -36,7 +36,7 @@ export type OnPointerDownParams = {
onConnect?: OnConnect; onConnect?: OnConnect;
onConnectEnd?: OnConnectEnd; onConnectEnd?: OnConnectEnd;
isValidConnection?: IsValidConnection; isValidConnection?: IsValidConnection;
onEdgeUpdateEnd?: (evt: MouseEvent | TouchEvent) => void; onReconnectEnd?: (evt: MouseEvent | TouchEvent) => void;
getTransform: () => Transform; getTransform: () => Transform;
getConnectionStartHandle: () => ConnectingHandle | null; getConnectionStartHandle: () => ConnectingHandle | null;
}; };
@@ -89,7 +89,7 @@ function onPointerDown(
onConnect, onConnect,
onConnectEnd, onConnectEnd,
isValidConnection = alwaysValid, isValidConnection = alwaysValid,
onEdgeUpdateEnd, onReconnectEnd,
updateConnection, updateConnection,
getTransform, getTransform,
getConnectionStartHandle, getConnectionStartHandle,
@@ -211,7 +211,7 @@ function onPointerDown(
onConnectEnd?.(event); onConnectEnd?.(event);
if (edgeUpdaterType) { if (edgeUpdaterType) {
onEdgeUpdateEnd?.(event); onReconnectEnd?.(event);
} }
cancelConnection(); cancelConnection();