Git Product home page Git Product logo

react-flow-smart-edge's Introduction

React Flow Smart Edge

Custom Edges for React Flow that never intersect with other nodes, using pathfinding.

CI Code Quality TypeScript Storybook Testing Library ESLint

Smart Edge

Install

With npm:

npm install @tisoap/react-flow-smart-edge

With yarn:

yarn add @tisoap/react-flow-smart-edge

This package is only compatible with version 11 or newer of React Flow Edge.

Support

Like this project and want to show your support? Buy me a coffee:

ko-fi

Really like this project? Sponsor me on GitHub:

GitHub Sponsors

Usage

This package ships with the following Smart Edges components:

  • SmartBezierEdge: A smart equivalent to React Flow's BezierEdge
  • SmartStraightEdge: A smart equivalent to React Flow's StraightEdge
  • SmartStepEdge: A smart equivalent to React Flow's StepEdge

Each one can be imported individually as a named export.

Example

import React from 'react'
import { ReactFlow } from 'reactflow'
import { SmartBezierEdge } from '@tisoap/react-flow-smart-edge'
import 'reactflow/dist/style.css'

const nodes = [
	{
		id: '1',
		data: { label: 'Node 1' },
		position: { x: 300, y: 100 }
	},
	{
		id: '2',
		data: { label: 'Node 2' },
		position: { x: 300, y: 200 }
	}
]

const edges = [
	{
		id: 'e21',
		source: '2',
		target: '1',
		type: 'smart'
	}
]

// You can give any name to your edge types
// https://reactflow.dev/docs/api/edges/custom-edges/
const edgeTypes = {
	smart: SmartBezierEdge
}

export const Graph = (props) => {
	const { children, ...rest } = props

	return (
		<ReactFlow
			defaultNodes={nodes}
			defaultEdges={edges}
			edgeTypes={edgeTypes}
			{...rest}
		>
			{children}
		</ReactFlow>
	)
}

Edge Options

All smart edges will take the exact same options as a React Flow Edge.

Custom Smart Edges

You can have more control over how the edge is rerendered by creating a custom edge and using the provided getSmartEdge function. It takes an object with the following keys:

  • sourcePosition, targetPosition, sourceX, sourceY, targetX and targetY: The same values your custom edge will take as props
  • nodes: An array containing all graph nodes, you can get it from the useNodes hook

Example

Just like you can use getBezierPath from reactflow to create a custom edge with a button, you can do the same with getSmartEdge:

import React from 'react'
import { useNodes, BezierEdge } from 'reactflow'
import { getSmartEdge } from '@tisoap/react-flow-smart-edge'

const foreignObjectSize = 200

export function SmartEdgeWithButtonLabel(props) {
	const {
		id,
		sourcePosition,
		targetPosition,
		sourceX,
		sourceY,
		targetX,
		targetY,
		style,
		markerStart,
		markerEnd
	} = props

	const nodes = useNodes()

	const getSmartEdgeResponse = getSmartEdge({
		sourcePosition,
		targetPosition,
		sourceX,
		sourceY,
		targetX,
		targetY,
		nodes
	})

	// If the value returned is null, it means "getSmartEdge" was unable to find
	// a valid path, and you should do something else instead
	if (getSmartEdgeResponse === null) {
		return <BezierEdge {...props} />
	}

	const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse

	return (
		<>
			<path
				style={style}
				className='react-flow__edge-path'
				d={svgPathString}
				markerEnd={markerEnd}
				markerStart={markerStart}
			/>
			<foreignObject
				width={foreignObjectSize}
				height={foreignObjectSize}
				x={edgeCenterX - foreignObjectSize / 2}
				y={edgeCenterY - foreignObjectSize / 2}
				requiredExtensions='http://www.w3.org/1999/xhtml'
			>
				<button
					onClick={(event) => {
						event.stopPropagation()
						alert(`remove ${id}`)
					}}
				>
					X
				</button>
			</foreignObject>
		</>
	)
}

Advanced Custom Smart Edges

The getSmartEdge function also accepts an optional object options, which allows you to configure aspects of the path-finding algorithm. You may use it like so:

const myOptions = {
	// your configuration goes here
	nodePadding: 20,
	gridRatio: 15
}

// ...

const getSmartEdgeResponse = getSmartEdge({
	sourcePosition,
	targetPosition,
	sourceX,
	sourceY,
	targetX,
	targetY,
	nodes,
	// Pass down options in the getSmartEdge object
	options: myOptions
})

The options object accepts the following keys (they're all optional):

  • nodePadding: How many pixels of padding are added around nodes, or by how much should the edge avoid the walls of a node. Default 10, minimum 2.
  • gridRatio: The size in pixels of each square grid cell used for path-finding. Smaller values for a more accurate path, bigger for faster path-finding. Default 10, minimum 2.
  • drawEdge: Allows you to change the function responsible to draw the SVG line, by default it's the same used by SmartBezierEdge (more below)
  • generatePath: Allows you to change the function for the path-finding, by default it's the same used by SmartBezierEdge (more below)

drawEdge

With the drawEdge option, you can change the function used to generate the final SVG path string, used to draw the line. By default it's the svgDrawSmoothLinePath function (same as used by the SmartBezierEdge), but the package also includes svgDrawStraightLinePath (same as used by the SmartStraightEdge and SmartStepEdge), or you can provide your own.

import {
	getSmartEdge,
	// Available built-in SVG draw functions
	svgDrawSmoothLinePath,
	svgDrawStraightLinePath
} from '@tisoap/react-flow-smart-edge'

// Using provided SVG draw functions:
const result = getSmartEdge({
	// ...
	options: {
		drawEdge: svgDrawSmoothLinePath
	}
})

// ...or using your own custom function
const result = getSmartEdge({
	// ...
	options: {
		drawEdge: (source, target, path) => {
			// your code goes here
			// ...
			return svgPath
		}
	}
})

The function you provided must comply with this signature:

type SVGDrawFunction = (
	source: XYPosition, // The starting {x, y} point
	target: XYPosition, // The ending  {x, y} point
	path: number[][] // The sequence of points [x, y] the line must follow
) => string // A string to be used in the "d" property of the SVG line

For inspiration on how to implement your own, you can check the drawSvgPath.ts source code.

generatePath

With the generatePath option, you can change the function used to do Pathfinding. By default, it's the pathfindingAStarDiagonal function (same as used by the SmartBezierEdge), but the package also includes pathfindingAStarNoDiagonal (used by SmartStraightEdge) and pathfindingJumpPointNoDiagonal (used by SmartStepEdge), or your can provide your own. The built-in functions use the pathfinding dependency behind the scenes.

import {
	getSmartEdge,
	// Available built-in pathfinding functions
	pathfindingAStarDiagonal,
	pathfindingAStarNoDiagonal,
	pathfindingJumpPointNoDiagonal
} from '@tisoap/react-flow-smart-edge'

// Using provided pathfinding functions:
const result = getSmartEdge({
	// ...
	options: {
		generatePath: pathfindingJumpPointNoDiagonal
	}
})

// ...or using your own custom function
const result = getSmartEdge({
	// ...
	options: {
		generatePath: (grid, start, end) => {
			// your code goes here
			// ...
			return { fullPath, smoothedPath }
		}
	}
})

The function you provide must comply with this signature:

type PathFindingFunction = (
	grid: Grid, // Grid representation of the graph
	start: XYPosition, // The starting {x, y} point
	end: XYPosition // The ending  {x, y} point
) => {
	fullPath: number[][] // Array of points [x, y] representing the full path with all points
	smoothedPath: number[][] // Array of points [x, y] representing a smaller, compressed path
} | null // The function should return null if it was unable to do pathfinding

For inspiration on how to implement your own, you can check the generatePath.ts source code and the pathfinding dependency documentation.

Advanced Examples

import {
	getSmartEdge,
	svgDrawSmoothLinePath,
	svgDrawStraightLinePath
	pathfindingAStarDiagonal,
	pathfindingAStarNoDiagonal,
	pathfindingJumpPointNoDiagonal
} from '@tisoap/react-flow-smart-edge'

// ...

// Same as importing "SmartBezierEdge" directly
const bezierResult = getSmartEdge({
	// ...
	options: {
		drawEdge: svgDrawSmoothLinePath,
		generatePath: pathfindingAStarDiagonal,
	}
})

// Same as importing "SmartStepEdge" directly
const stepResult = getSmartEdge({
	// ...
	options: {
		drawEdge: svgDrawStraightLinePath,
		generatePath: pathfindingJumpPointNoDiagonal,
	}
})

// Same as importing "SmartStraightEdge" directly
const straightResult = getSmartEdge({
	// ...
	options: {
		drawEdge: svgDrawStraightLinePath,
		generatePath: pathfindingAStarNoDiagonal,
	}
})

Storybook

You can see live Storybook examples by visiting this page, and see their source code here.

License

This project is MIT licensed.

react-flow-smart-edge's People

Contributors

tisoap avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-flow-smart-edge's Issues

In version 3.0 Beta - Edge between 2 nodes goes away if the nodes are close to each other

Me and @antipasvasil are collogues and are working on the Beta version. There is a problem when 2 nodes are close to each other - the edge between them goes to a fixed location(at (0, 0) coordinates.

To Reproduce
Steps to reproduce the behavior:

  1. Go to any nodes that have connection (Edge) between them
  2. Start dragging one of the node towards the other node that is connected
  3. As they get closer the connection (Edge) has been transferred to 0,0 coordinates

Expected behavior
No matter how close any nodes that are connected are getting close the connection should remain between them and not disappear

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):
OS: Windows 10, 11
Browser Chrome, Firefox
screen_1
Screen_2

Add draggable point to smart edge

feature

  • draggable
  • show it on focus
  • save coordinate of it
  • update those point position with pathfinder
  • if user drag the point find path from that point
  • pathfinder avoid collapse between edge

EX

Screenshot from 2022-07-10 15-45-30

Screenshot from 2022-07-10 15-24-10

thx for your great work

Allow developers to change the path finding function

First of all, thanks for the great package! It saves me tons of time.

Originally, the package did not seem to be "smart" on my end (still using the BezierEdge from react-flow). I then found out that the length of smoothedPath for me is always smaller or equal to 2, which fallbacks to the edges of react-flow (see codes here). Then I was thinking it cannot be that smoothedPath is always that case. It turns out there is a bug in the dependency pathfinding, where no coordinate will be recorded if coming across a block (start and end coordinate will not be updated either).

function smoothenPath(grid, path) {
        ....
        blocked = false;
        ....
        if (blocked) {
            lastValidCoord = path[i - 1]; // THIS IS NOT DEFINED AND CAUSE AN INTERNAL ERROR
            newPath.push(lastValidCoord);
            sx = lastValidCoord[0];
            sy = lastValidCoord[1];
        }
    }
    
    newPath.push([x1, y1]);

    return newPath;
}

The fix is easy but it seems that no one is maintaining pathfinding anymore (e.g., qiao/PathFinding.js#192).

Suggestions

  1. Maybe react-flow-smart-edge should use a fork of pathfinding to have known bugs fixed?
  2. Even better, maybe we can find a more up-to-date package related to graph theory as this might be maintainable in the long run?

Option to propagate exceptions outside of getSmartEdge

Is your feature request related to a problem? Please describe.

We'd like to better understand the situations in which getSmartEdge returns null. We get reports through metrics of this occurring in production but have not been able to repro locally.

Describe the solution you'd like

diff --git a/src/getSmartEdge/index.ts b/src/getSmartEdge/index.ts
index 75e0f7f..3330734 100644
--- a/src/getSmartEdge/index.ts
+++ b/src/getSmartEdge/index.ts
@@ -28,6 +28,7 @@ export type GetSmartEdgeOptions = {
        nodePadding?: number
        drawEdge?: SVGDrawFunction
        generatePath?: PathFindingFunction
+       propagateError?: boolean
 }
 
 export type GetSmartEdgeParams<NodeDataType = unknown> = EdgeParams & {
@@ -128,7 +129,10 @@ export const getSmartEdge = <NodeDataType = unknown>({
                )
 
                return { svgPathString, edgeCenterX, edgeCenterY }
-       } catch {
+       } catch (e) {
+               if (options.propagateError) {
+                       throw e;
+               }
                return null
        }
 }

Describe alternatives you've considered

We could also fork the repo if this approach isn't appealing, though would love to stay on the main branch for future updates.

Additional context

Happy to open up a PR for this if I can get write permissions

Smart Edge wrong behaviour on Sub Flows

First of all, I thank you for your great work.

The issue is drawing edges in subflows is wrong. In the below figures parentNode of the smaller nodes is the WHILE node.

Expected behaviour:
image
It should be drawn like this for all positions inside the parent node.

Actual Result:
image
After moving a little bit on one of the nodes, the edge was drawn wrong.

Maybe something similar to #28 can solve this.

Separate website for documentation

As the library grows in API size, it becomes more difficult to read about the available options on the repository README. Ideally this library should have a seperate website for documentation, with separate pages for each option and live intractable examples, same as the React Flow docs. They mentioned in their blog post that they're using Docusaurus, will need to check it out.

Ideally the documentation should be all statically build, and I should be able to deploy it using gh-pages, to save on server and domain costs. The current GitHub page hosts the Storybook examples and tests, but they can be moved to a free tier on Chromatic.

Connection line appears broken when using specific grid snapping

Is your feature request related to a problem? Please describe.

Hello @tisoap we are having the following situation when using SmartEdge with GridSnapping

we are having custome grid snaping position and when we connect a parent node to three child nodes at some point the connection gets broken and it's not always a straight line.

My question is, is there a way always to be sure to make the connection straight when using StepEdge, can you suggest a fix if you have ever come across such a problem.

The code for what we use is as follows for the gird snapping and smartEdge:

export const snapGridValue: SnapGridValueProps = { snapGrid: [90, 60], snapToGrid: true, backgroundGap: [90, 60], sizeCrossDots: 40, backgroundGridColor: '#e1e1e1', }

const getSmartEdgeResponse = getSmartEdge({ sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, nodes: updatedNodes, options: { drawEdge: svgDrawStraightLinePath, generatePath: pathfindingJumpPointNoDiagonal, }, })

Describe the solution you'd like

We have been thinking that we might need to create a custom function for svgDrawStraightLinePath if there is no other way.

Describe alternatives you've considered

Other way is to have a custom implementation for a position algorithm because in order for the nodes to always stayed at some position that will not allow for the connections to become broken, but there is a lot of different cases and there always might be some discrepancies

Additional context

Here is an image of the issue that we are tying to solve.

image-2022-12-01-08-52-49-896

Edge labels getting overlapped

Describe the Bug

We have used this library in our application for connecting two edges. Theres's an issue that we have noticed that the edge labels are getting overlapped one over the other as we have lot of nodes connecting each other.

Minimal Example

https://codesandbox.io/s/edge-overlapping-32omg0?file=/src/Flow.js

Steps to Reproduce the Bug or Issue

Go to the code sandbox, we can see the edge labels getting overlapped on each other.

Expected behavior

As a user, we would like the edges not getting overlapped and should be drawn in such a way that both the labels should be displayed properly.

Is there any way we can achieve this by providing or customising the props, that also would be much helpful for us.

Screenshots or Videos

image

Platform

  • OS: macOS, Windows, Linux
  • Browser: Chrome, Safari, Firefox

Additional context

No response

Edges not starting/ending on XY coords

Describe the Bug

I would expect the edges to start and end on the provided XY coordinates, but they don't.

Used props:

    const getSmartEdgeReturn = getSmartEdge({
      sourceX: (maxX + defaultNodeWidth + minX) / 2,
      sourceY: (maxY + defaultNodeHeight + 20),
      sourcePosition: Position.Bottom,
      targetX: parentNode.position.x + defaultNodeWidth * 0.73,
      targetY: parentNode.position.y + defaultNodeHeight / 2,
      targetPosition: Position.Right,
      nodes: flowInstance.getNodes(),
      options: {
        nodePadding: defaultNodeWidth / 4,
        drawEdge: svgDrawStraightLinePath,
        generatePath: pathfindingJumpPointNoDiagonal,
      }
    });

Minimal Example

/

Steps to Reproduce the Bug or Issue

/

Expected behavior

Line should start and end on the provided coordinates.

Screenshots or Videos

Issue

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Safari, Firefox]
  • Version: [e.g. 91.1]

Additional context

No response

Make edges not overlap each other

Is your feature request related to a problem? Please describe.

There are multiple nodes layouted^TM by elkjs and afterwards painted on the canvas. The nodes are not draggable, so the user can change the position and trigger the recalculation of the edges by PathFinding.js.
The Problem here is, that the user is not able to recognize which edge connects which nodes.

Describe the solution you'd like

I thought that marking the edge path points via setWalkableAt as not walkable would force the edges to not overlay each other anymore. What do you think about this?

Describe alternatives you've considered

Hacking on the PathFinding.js implementation.

Additional context

image

Add helper function for EdgeTypes and Options

Is your feature request related to a problem? Please describe.

Currently introducing an option (such as gridRatio) is appears to be quite burdensome requiring the creation of a whole custom SmartEdge

Would it be possible to introduce a helper function to apply options to edge types?

Describe the solution you'd like

const edgeTypes :EdgeTypes = {
  smartstep: getSmartStepEdgeType(options)
}

...

return (
      <ReactFlow edgeTypes={edgeTypes} ... />

Describe alternatives you've considered

Creating a custom smart edge.

Additional context

No response

Smart Edge Not Considering nodes inside a group.

Describe the Bug

im facing an issue while using the custom edge example from the docs,

case 1
Screenshot 2023-03-09 at 12 32 14 AM

case 2
Screenshot 2023-03-09 at 12 42 19 AM

The connection of edges can be made within the sub-flow or in between another group or a node from outside of the group.

here is my custom edge component
`import { useNodes, BezierEdge } from 'reactflow';
import { getSmartEdge, svgDrawStraightLinePath, pathfindingJumpPointNoDiagonal } from '@tisoap/react-flow-smart-edge';
import { AStarFinder, JumpPointFinder, Util, DiagonalMovement } from 'pathfinding';
export function SmartEdgeWithSubFlow(props: any) {
const { id, sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, style, markerStart, markerEnd } =
props;

const nodes = useNodes();
console.log('nodes :>> ', nodes);
const getSmartEdgeResponse = getSmartEdge({
    sourcePosition,
    targetPosition,
    sourceX,
    sourceY,
    targetX,
    targetY,
    nodes,
    options: {
        drawEdge: svgDrawStraightLinePath,
        generatePath: (grid, start, end) => {
            try {
                // FIXME: The "pathfinding" module doe not have proper typings.
                // @ts-ignore
                const finder = new JumpPointFinder({
                    diagonalMovement: DiagonalMovement.Never,
                });
                console.log('grid :>> ', grid);
                console.log('finder :>> ', finder);
                console.log('start :>> ', start);
                console.log('end :>> ', end);
                const fullPath = finder.findPath(start.x, start.y, end.x, end.y, grid);
                const smoothedPath = fullPath;
                if (fullPath.length === 0 || smoothedPath.length === 0) return null;
                console.log('fullPath :>> ', fullPath);
                console.log('smoothedPath :>> ', smoothedPath);
                return { fullPath, smoothedPath };
            } catch {
                return null;
            }
        },
        gridRatio: 2,
        nodePadding: 20,
    },
});

// If the value returned is null, it means "getSmartEdge" was unable to find
// a valid path, and you should do something else instead
// console.log('getSmartEdgeResponse :>> ', getSmartEdgeResponse);
if (getSmartEdgeResponse === null) {
    console.log('null :>> ', null);
    return <BezierEdge {...props} />;
}

const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse;

return (
    <>
        <path
            style={style}
            className="react-flow__edge-path"
            d={svgPathString}
            markerEnd={markerEnd}
            markerStart={markerStart}
        />
    </>
);

}
`

My findings and requirements:

  1. A group is also considered a node(or obstacle) and so in case 2 you can see that the edge is going around the group border, I want to check a condition if target node is within the group don't consider the group to be a node and don't go around the group, but still consider other nodes within the group as obstacles.
  2. If the edge is coming from or to another node or group outside the current group, similar to the condition above, consider all nodes to be obstacles but don't consider the group to be an obstacle

It would be great if you can help me out on this one

Minimal Example

https://github.com/tisoap/react-flow-smart-edge#custom-smart-edges

Steps to Reproduce the Bug or Issue

  1. Use a reactflow boiler plate

  2. using this component as your edgeType
    `import { useNodes, BezierEdge } from 'reactflow';
    import { getSmartEdge, svgDrawStraightLinePath, pathfindingJumpPointNoDiagonal } from '@tisoap/react-flow-smart-edge';
    import { AStarFinder, JumpPointFinder, Util, DiagonalMovement } from 'pathfinding';
    export function SmartEdgeWithSubFlow(props: any) {
    const { id, sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, style, markerStart, markerEnd } =
    props;

    const nodes = useNodes();
    console.log('nodes :>> ', nodes);
    const getSmartEdgeResponse = getSmartEdge({
    sourcePosition,
    targetPosition,
    sourceX,
    sourceY,
    targetX,
    targetY,
    nodes,
    options: {
    drawEdge: svgDrawStraightLinePath,
    generatePath: (grid, start, end) => {
    try {
    // FIXME: The "pathfinding" module doe not have proper typings.
    // @ts-ignore
    const finder = new JumpPointFinder({
    diagonalMovement: DiagonalMovement.Never,
    });
    console.log('grid :>> ', grid);
    console.log('finder :>> ', finder);
    console.log('start :>> ', start);
    console.log('end :>> ', end);
    const fullPath = finder.findPath(start.x, start.y, end.x, end.y, grid);
    const smoothedPath = fullPath;
    if (fullPath.length === 0 || smoothedPath.length === 0) return null;
    console.log('fullPath :>> ', fullPath);
    console.log('smoothedPath :>> ', smoothedPath);
    return { fullPath, smoothedPath };
    } catch {
    return null;
    }
    },
    gridRatio: 2,
    nodePadding: 20,
    },
    });

    // If the value returned is null, it means "getSmartEdge" was unable to find
    // a valid path, and you should do something else instead
    // console.log('getSmartEdgeResponse :>> ', getSmartEdgeResponse);
    if (getSmartEdgeResponse === null) {
    console.log('null :>> ', null);
    return <BezierEdge {...props} />;
    }

    const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse;

    return (
    <>

    </>
    );
    }
    `

  3. make connections between sub-flows and stand alone nodes, connections between nodes within the subflows like in the 2 images

Expected behavior

  1. A group is also considered a node(or obstacle) and so in case 2 you can see that the edge is going around the group border, I want to check a condition if target node is within the group don't consider the group to be a node and don't go around the group, but still consider other nodes within the group as obstacles.
  2. If the edge is coming from or to another node or group outside the current group, similar to the condition above, consider all nodes to be obstacles but don't consider the group to be an obstacle

Screenshots or Videos

No response

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Safari, Firefox]
  • Version: [e.g. 91.1]

Additional context

No response

Add option for squared off edges

Nice work!

I was wondering if there was a way to make the edges squared off instead of the non-uniform curves that it currently draws.

Add label support

smart edge don't show the edge label, thats cool if there is some basic support.

Provide support for custom Edge labels

First of all thank you @tisoap for this amazing library.

We have a requirement of displaying a button along with the edge label, through which we want to perform some actions. Something similar to what we have as CustomEdge in react-flow.

Below is the screenshot of what we are actually trying to achieve

Screenshot 2022-04-26 at 1 04 31 PM

Update to be compatible with React Flow 11

It was mentioned: "This package is only compatible with version 10 or newer of React Flow Edge."

  • Actualy it is not compatable with v.11 of it. (here)
  • we migrated to v.11 of react-flow and when we started our project we had and still having an error:
    Screenshot 2022-10-10 140639

The library react-flow-smart-edge looking for old dependency of react-flow : "react-flow-renderer" but it should be reactflow

So, what can be done about it?

Props that are generated when you start dragging new connection are missing for <StepEdge /> in react flow v11

On previous version of ReactFlow v10 whenever you start dragging new connection (Edge) to connect towards a new node the props that were coming and that were needed for were sourceX sourceY and targetX targetY everything was working as it should be, while as after updating to ReactFlow v11 and SmartEdge v3.0 when you start to create a connection the line is disappearing and you can't see it until you connect it, and the props that are specified are missing you got an error as well because of that.

Minimal Example
Share an URL with a minimal example on CodeSandbox or a minimal GitHub repository where the error happens. Reported bugs without this link will not be worked on!

To Reproduce
Steps to reproduce the behavior:

  1. Update to ReactFlow v11
  2. Select and Edge and start dragging new connection
  3. The connection is not visible
  4. Until you connect it to the new node and props are missing

Expected behavior
The connection should be visible from the begging of the dragging and props shouldn't be missing

Actual behavior
The connection is disappearing and the props are missing

Desktop (please complete the following information):

  • OS: [Windows 10-11]
  • Browser [chrome, firefox]
  • Version [latest]

Screenshots and Videos

React flow v10 SmartEdge v2.0.0
React_flow_v10
https://user-images.githubusercontent.com/52380770/199692811-140fe4b3-1109-406f-88e1-b3ecb8e4cc76.mp4

React flow v11 SmartEdge v3.0.0 beta
React_flow_v11
https://user-images.githubusercontent.com/52380770/199693387-30f6b75e-ab72-4b0a-8083-ab9b64134d8e.mp4

Update Sponsor Badge

I've been approved for GitHub Sponsors! ๐Ÿฅณ๐ŸŽ‰

So I need to updates the repository's .github/FUNDING.yml file to include the GitHub sponsor option, together with a badge on the project's README

How to integrate it with existing custom edge?

Hi. I have multiple types of edges in my setup. I want to make each one of them smart. From the docs, if we give the type as SmartEdge, it doesn't intersect. How can I make my custom edge inherit these properties and on top of them use properties which are unique to them?

Make it possible to use different types of Smart Edges at the same time

Hello dear,
This is pretty awesome feature that you have developed. lots of appreciation for this. i have been using this nice feature with React flow. during the development I got a weird problem. SmartEdgeProvider wrap React flow, whenever i change the SmartEdgeProvider options then smart edge applies for all edges. and this is not fulfilling my requirement. could you tell me please is it possible to control smart edge individually or if this feature is not available could you add this feature please? you can see a video below where i have highlighted smart edges with green color.

smart-edge.mp4

How to add buttons to the edges?

image
Hey @tisoap,
I am going to implement SmartStetpEdge with( importing {SmartStepEdge} from '@tisoap/react-flow-smart-edge') Button but I didn't see any methods like getBezierPath, getSmoothStepPath
Could you please help me on that

Describe supported React Flow versions on README

image

while working on current version v1.0.0 facing the above issue but I used version 0.4.0 its worked well now I need to implement SmartStepEdge using version v1.0.0
Need guidance.
Thanks in advance

NextJS error when importing SmartEdge and SmartEdgeProvider

In NextJS 12.1.0, I used React Flow v10 with SmartEdge v0.5.0, and tried to import like your document

import ReactFlow, {
  addEdge,
  Background,
  useNodesState,
  useEdgesState,
  MiniMap,
  Controls,
  Node,
} from "react-flow-renderer";
import { SmartEdge, SmartEdgeProvider } from "@tisoap/react-flow-smart-edge";

//.......................

const edgeTypes = {
  smart: SmartEdge,
};

//.......................

const WorkflowContainer = () => {
  //..........................

  return (
      <SmartEdgeProvider options={{ debounceTime: 300 }}>
        <ReactFlow
          className="react-flow-subflows-example"
          nodes={nodes}
          edges={edges}
          onNodeMouseEnter={(
            event: MouseEvent<Element, globalThis.MouseEvent>,
            node: Node<any>
          ) => {
            handleNodeMouseEnter(event, node);
          }}
          // onNodeDragStop
          onNodesChange={onNodesChange}
          onEdgesChange={onEdgesChange}
          nodeTypes={nodeTypes}
          edgeTypes={edgeTypes}
          // onConnect={onConnect}
          fitView
        >
          <MiniMap />
          <Controls />
          <Background />
        </ReactFlow>
      </SmartEdgeProvider>
  );
};

export default WorkflowContainer;

But the browser showed the error:

Error: require() of ES Module D:\digi-curriculum\digi-curriculum-frontend\node_modules\react-flow-renderer\dist\esm\index.js from D:\digi-curriculum\digi-curriculum-frontend\node_modules@tisoap\react-flow-smart-edge\dist\react-flow-smart-edge.cjs.development.js not supported.

Instead change the require of index.js in D:\digi-curriculum\digi-curriculum-frontend\node_modules@tisoap\react-flow-smart-edge\dist\react-flow-smart-edge.cjs.development.js to a dynamic import() which is available in all CommonJS modules.

engine warning when installing latest version

Describe the Bug

npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@tisoap/[email protected]',
npm WARN EBADENGINE   required: { node: '>=16', npm: '^8.0.0' },
npm WARN EBADENGINE   current: { node: 'v18.17.1', npm: '9.6.7' }
npm WARN EBADENGINE }

Minimal Example

n/a

Steps to Reproduce the Bug or Issue

nvm use "lts/*"
npm install @tisoap/react-flow-smart-edge

Expected behavior

should not warn

Screenshots or Videos

No response

Platform

node v18

Additional context

deps in main already mention node 18, just need to publish

edgeCenterX and edgeCenterY sometimes aren't calculated properly!

Describe the Bug

Hello @tisoap,

Thanks for this awesome library.
I noticed that when you use the following code:

    const { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse;
       return (
        <>
            <BlockEdge {...props} />

            <EdgeLabelRenderer>
                <div
                    style={{
                        position: 'absolute',
                        transform: `translate(-50%, -50%) translate(${edgeCenterX}px,${edgeCenterY}px)`,
                        fontSize: 12,
                        // everything inside EdgeLabelRenderer has no pointer events by default
                        // if you have an interactive element, set pointer-events: all
                        pointerEvents: 'all',
                    }}
                    className="nodrag nopan"
                >
                    <div className="edgebutton">
                        <LogicIcon />
                    </div>
                </div>
            </EdgeLabelRenderer>
        </>
    );

This edge button sometime isn't on the path itself when you try dragging the node.

Minimal Example

N/A

Steps to Reproduce the Bug or Issue

1- Try to add an edge button
2- Try dragging the nodes
3- You will notice that the edge button isn't always on the path.

Expected behavior

The edge button x and y should be always on the path.

Screenshots or Videos

Video: https://www.awesomescreenshot.com/video/18125673?key=f23c09850e5998229585d2a49ea8a2f6

Platform

OS: [Windows]

Additional context

No response

Bending of edge from source

Describe the Bug

The edge seems to have a bend when it origins from the source. After that it's coming as expected (I tried for smooth step edge). Is there any way to avoid that? Please help me out here

Screenshot 2023-04-17 at 3 43 00 PM

Even if you check in the codesandbox example(not mine) given below, you will be able to see the issue

Minimal Example

https://codesandbox.io/s/old-rgb-k9buls

Steps to Reproduce the Bug or Issue

  1. Create a smooth step edge
  2. You will see a bend at the source

Expected behavior

Expected to see no bend. If the line is a straight line, from the source itself, it should be straight

Screenshots or Videos

No response

Platform

  • OS: Mac
  • Browser: Chrome

Additional context

No response

Connection line appears broken when using specific grid snapping

Describe the Bug

Is your feature request related to a problem? Please describe.
Hello @tisoap we are having the following situation when using SmartEdge with GridSnapping

we are having custome grid snaping position and when we connect a parent node to three child nodes at some point the connection gets broken and it's not always a straight line.

My question is, is there a way always to be sure to make the connection straight when using StepEdge, can you suggest a fix if you have ever come across such a problem.

The code for what we use is as follows for the gird snapping and smartEdge:

export const snapGridValue: SnapGridValueProps = { snapGrid: [90, 60], snapToGrid: true, backgroundGap: [90, 60], sizeCrossDots: 40, backgroundGridColor: '#e1e1e1', }

const getSmartEdgeResponse = getSmartEdge({ sourcePosition, targetPosition, sourceX, sourceY, targetX, targetY, nodes: updatedNodes, options: { drawEdge: svgDrawStraightLinePath, generatePath: pathfindingJumpPointNoDiagonal, }, })

Minimal Example

https://codesandbox.io/s/trusting-rubin-nus8rh

Steps to Reproduce the Bug or Issue

Add three nodes
Connect them to the parent node and spred them one to another
and observe the behavior of the connection line.

Expected behavior

Connection line should be straight after the first step edge

Screenshots or Videos

image
image-2022-12-01-08-52-49-896

Platform

  • OS: [e.g. macOS, Windows, Linux]
  • Browser: [e.g. Chrome, Safari, Firefox]
  • Version: [e.g. 91.1]

Additional context

No response

Add SmoothStepPath

Is your feature request related to a problem? Please describe.

Please add SmoothStepPath

Describe the solution you'd like

I want Smooth Step Path edges ๐Ÿ™‚

Describe alternatives you've considered

No alternative

Additional context

No response

Edges are still overlapped on bidirectional connections

If you have something like:

{ id: 'e4-5', source: '4', target: '5', arrowHeadType: 'arrowclosed', label: 'label e-4-5', }, { id: 'e5-4', source: '5', target: '4', type: 'smoothstep', label: 'label e-5-4' },

they will look overlapped.

Create templates for new issues

With the increase in issues reported, this library needs a template for users to create new issues. At least two templates, one for feature suggestions and another for bug reports. The bug report one should make it clear that the user must provide a a minimal example on CodeSandbox or a minimal GitHub repository where the error happens.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.