{"_id":"@jalez/react-flow-smart-edge","name":"@jalez/react-flow-smart-edge","dist-tags":{"latest":"4.0.0"},"versions":{"4.0.0":{"name":"@jalez/react-flow-smart-edge","version":"4.0.0","description":"Smart edge routing for @xyflow/react v12+ (maintained fork of @tisoap/react-flow-smart-edge)","keywords":["react","typescript","graph","flow","flowchart","smart","edge","pathfinding","react-flow-smart-edge","xyflow","fork","maintained"],"homepage":"https://jalez.github.io/react-flow-smart-edge/","repository":{"type":"git","url":"git+https://github.com/jalez/react-flow-smart-edge.git"},"license":"MIT","author":{"name":"Jaakko Rajala","email":"jaakko.rajala@tuni.fi"},"contributors":[{"name":"Tiso Alvarez Puccinelli","url":"original author"}],"type":"module","main":"dist/index.js","module":"dist/react-flow-smart-edge.esm.js","typings":"dist/index.d.ts","scripts":{"build":"npm run build-component","build-component":"dts build","check-types":"tsc --noEmit","chromatic":"chromatic --exit-zero-on-changes --project-token f5598c842f1a","deploy-component":"np --any-branch","install-playwright":"playwright install --with-deps","lint":"dts lint src","lint-fix":"dts lint src --fix","predeploy":"npm run build","prepare":"dts build","start":"dts watch","test":"npm run check-types && npm run lint","ui":"npm update --save-dev"},"husky":{"hooks":{"pre-commit":"dts lint"}},"resolutions":{"string-width":"^4.2.3","strip-ansi":"^6.0.1"},"dependencies":{"pathfinding":"^0.4.18"},"devDependencies":{"@babel/core":"^7.27.4","@babel/plugin-syntax-flow":"^7.27.1","@babel/plugin-transform-react-jsx":"^7.27.1","@babel/preset-env":"^7.27.2","@babel/preset-react":"^7.27.1","@babel/preset-typescript":"^7.27.1","@shopify/eslint-plugin":"^43.0.0","@tisoap/eslint-config-ts-react":"^7.0.0","@types/minimist":"^1.2.5","@types/node":"^20.19.1","@types/pathfinding":"^0.1.0","@types/react":"^18.3.23","@types/react-dom":"^18.3.7","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","chromatic":"^7.6.0","dts-cli":"^2.0.5","eslint":"^8.57.1","eslint-config-prettier":"^10.1.5","eslint-plugin-flowtype":"^8.0.3","eslint-plugin-import":"^2.32.0","eslint-plugin-jest-dom":"^5.5.0","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-prettier":"^5.5.1","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^4.6.2","eslint-plugin-react-prefer-function-component":"^3.4.0","eslint-plugin-sonarjs":"^0.21.0","eslint-plugin-testing-library":"^6.5.0","eslint-plugin-unicorn":"^48.0.1","gh-pages":"^6.3.0","husky":"^9.1.7","jest":"^29.7.0","jest-circus":"^29.7.0","jest-environment-node":"^29.7.0","np":"^10.2.0","playwright":"^1.53.1","prettier":"^3.6.1","react":"^18.3.1","react-dom":"^18.3.1","@xyflow/react":"^12.5.0","require-from-string":"^2.0.2","string-width":"^4.2.3","strip-ansi":"^6.0.1","typescript":"^5.8.3","webpack":"^5.99.9"},"peerDependencies":{"react":">=17","react-dom":">=17","@xyflow/react":">=12","typescript":">=4.6"},"engines":{"node":">=18","npm":">=8"},"_id":"@jalez/react-flow-smart-edge@4.0.0","gitHead":"01d4baeb549d95c4b010920be8a954344144319f","bugs":{"url":"https://github.com/jalez/react-flow-smart-edge/issues"},"_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-6L6QS9syf8IxMEP8AtYIwc9ZaeAz+fvzFetOkbl1/fYd3vQHXjZFFI8TosZasbUMXw5dLcBSkcB5BnvGnF6V9g==","shasum":"ff54f7a41b104ce89c6c4ea6b64fe08ab9d3879a","tarball":"https://registry.npmjs.org/@jalez/react-flow-smart-edge/-/react-flow-smart-edge-4.0.0.tgz","fileCount":38,"unpackedSize":205991,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCKZivFqA/YjrvgjmkeNVhO+VPADfdPkCHOC8gWQKvjgQIhAN6I4oJVAdZ9Bhyt1qW7hbPJmrmV9j/ft5Luix7UZBrv"}]},"_npmUser":{"name":"jalez","email":"raitsu11@gmail.com","actor":{"name":"jalez","email":"raitsu11@gmail.com","type":"user"}},"directories":{},"maintainers":[{"name":"jalez","email":"raitsu11@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-flow-smart-edge_4.0.0_1750890025726_0.3829002279100875"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-25T22:20:25.586Z","4.0.0":"2025-06-25T22:20:25.919Z","modified":"2025-06-25T22:20:26.249Z"},"maintainers":[{"name":"jalez","email":"raitsu11@gmail.com"}],"description":"Smart edge routing for @xyflow/react v12+ (maintained fork of @tisoap/react-flow-smart-edge)","homepage":"https://jalez.github.io/react-flow-smart-edge/","keywords":["react","typescript","graph","flow","flowchart","smart","edge","pathfinding","react-flow-smart-edge","xyflow","fork","maintained"],"repository":{"type":"git","url":"git+https://github.com/jalez/react-flow-smart-edge.git"},"contributors":[{"name":"Tiso Alvarez Puccinelli","url":"original author"}],"author":{"name":"Jaakko Rajala","email":"jaakko.rajala@tuni.fi"},"bugs":{"url":"https://github.com/jalez/react-flow-smart-edge/issues"},"license":"MIT","readme":"# React Flow Smart Edge v12+\n\n> **Maintained fork** of [@tisoap/react-flow-smart-edge](https://github.com/tisoap/react-flow-smart-edge) by Tiso Alvarez Puccinelli  \n> Updated for **@xyflow/react v12+** with zero security vulnerabilities\n\nCustom Edges for React Flow that never intersect with other nodes, using pathfinding.\n\n![TypeScript](https://shields.io/badge/TypeScript-3178C6?logo=TypeScript&logoColor=white)\n![ESLint](https://img.shields.io/badge/ESLint-3A33D1?logo=eslint&logoColor=white)\n![Zero Vulnerabilities](https://img.shields.io/badge/Security-Zero%20Vulnerabilities-brightgreen)\n![React Flow v12](https://img.shields.io/badge/@xyflow/react-v12+-blue)\n\n![Smart Edge](https://raw.githubusercontent.com/tisoap/react-flow-smart-edge/main/.github/images/example.gif)\n\n## Why This Fork?\n\nThe original [@tisoap/react-flow-smart-edge](https://github.com/tisoap/react-flow-smart-edge) has been **archived** and unmaintained for 3+ years. This fork provides:\n\n- ✅ **@xyflow/react v12+ compatibility** (migrated from deprecated `reactflow` package)\n- ✅ **Zero security vulnerabilities** (was 22+ in original)\n- ✅ **Reduced bundle size** (removed Storybook dependencies)\n- ✅ **Updated dependencies** (all packages updated to latest compatible versions)\n- ✅ **Modern TypeScript** support (TypeScript 5.8+)\n- ✅ **Active maintenance** (accepting issues and PRs)\n\n## Migration from Original\n\nIf you're using the original package:\n\n```bash\n# Remove old package\nnpm uninstall @tisoap/react-flow-smart-edge reactflow\n\n# Install new packages  \nnpm install @jalez/react-flow-smart-edge @xyflow/react\n```\n\nThe API remains **100% compatible** - just update your imports:\n\n```typescript\n// Update your React Flow imports\nimport { ReactFlow, Node, Edge } from '@xyflow/react'\nimport '@xyflow/react/dist/style.css'\n\n// Smart Edge imports remain the same\nimport { SmartBezierEdge } from '@jalez/react-flow-smart-edge'\n```\n\n## Install\n\nWith `npm`:\n\n```bash\nnpm install @jalez/react-flow-smart-edge @xyflow/react\n```\n\nWith `yarn`:\n\n```bash\nyarn add @jalez/react-flow-smart-edge @xyflow/react\n```\n\nThis package is compatible with **@xyflow/react v12+** (the new official React Flow package).\n\n## Usage\n\nThis package ships with the following Smart Edges components:\n\n- `SmartBezierEdge`: A smart equivalent to React Flow's [BezierEdge](https://reactflow.dev/docs/api/edges/edge-types/)\n- `SmartStraightEdge`: A smart equivalent to React Flow's [StraightEdge](https://reactflow.dev/docs/api/edges/edge-types/)\n- `SmartStepEdge`: A smart equivalent to React Flow's [StepEdge](https://reactflow.dev/docs/api/edges/edge-types/)\n\nEach one can be imported individually as a named export.\n\n### Example\n\n```jsx\nimport React from 'react'\nimport { ReactFlow } from '@xyflow/react'\nimport { SmartBezierEdge } from '@jalez/react-flow-smart-edge'\nimport '@xyflow/react/dist/style.css'\n\nconst nodes = [\n\t{\n\t\tid: '1',\n\t\tdata: { label: 'Node 1' },\n\t\tposition: { x: 300, y: 100 }\n\t},\n\t{\n\t\tid: '2',\n\t\tdata: { label: 'Node 2' },\n\t\tposition: { x: 300, y: 200 }\n\t}\n]\n\nconst edges = [\n\t{\n\t\tid: 'e21',\n\t\tsource: '2',\n\t\ttarget: '1',\n\t\ttype: 'smart'\n\t}\n]\n\n// You can give any name to your edge types\n// https://reactflow.dev/docs/api/edges/custom-edges/\nconst edgeTypes = {\n\tsmart: SmartBezierEdge\n}\n\nexport const Graph = (props) => {\n\tconst { children, ...rest } = props\n\n\treturn (\n\t\t<ReactFlow\n\t\t\tdefaultNodes={nodes}\n\t\t\tdefaultEdges={edges}\n\t\t\tedgeTypes={edgeTypes}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{children}\n\t\t</ReactFlow>\n\t)\n}\n```\n\n## Edge Options\n\nAll smart edges will take the exact same options as a [React Flow Edge](https://reactflow.dev/docs/api/edges/edge-options/).\n\n## Custom Smart Edges\n\nYou can have more control over how the edge is rerendered by creating a [custom edge](https://reactflow.dev/docs/api/edges/custom-edges/) and using the provided `getSmartEdge` function. It takes an object with the following keys:\n\n- `sourcePosition`, `targetPosition`, `sourceX`, `sourceY`, `targetX` and `targetY`: The same values your [custom edge](https://reactflow.dev/docs/examples/edges/custom-edge/) will take as props\n- `nodes`: An array containing all graph nodes, you can get it from the [`useNodes` hook](https://reactflow.dev/docs/api/hooks/use-nodes/)\n\n### Example\n\nJust like you can use `getBezierPath` from `reactflow` to create a [custom edge with a button](https://reactflow.dev/docs/examples/edges/edge-with-button/), you can do the same with `getSmartEdge`:\n\n```jsx\nimport React from 'react'\nimport { useNodes, BezierEdge } from '@xyflow/react'\nimport { getSmartEdge } from '@jalez/react-flow-smart-edge'\n\nconst foreignObjectSize = 200\n\nexport function SmartEdgeWithButtonLabel(props) {\n\tconst {\n\t\tid,\n\t\tsourcePosition,\n\t\ttargetPosition,\n\t\tsourceX,\n\t\tsourceY,\n\t\ttargetX,\n\t\ttargetY,\n\t\tstyle,\n\t\tmarkerStart,\n\t\tmarkerEnd\n\t} = props\n\n\tconst nodes = useNodes()\n\n\tconst getSmartEdgeResponse = getSmartEdge({\n\t\tsourcePosition,\n\t\ttargetPosition,\n\t\tsourceX,\n\t\tsourceY,\n\t\ttargetX,\n\t\ttargetY,\n\t\tnodes\n\t})\n\n\t// If the value returned is null, it means \"getSmartEdge\" was unable to find\n\t// a valid path, and you should do something else instead\n\tif (getSmartEdgeResponse === null) {\n\t\treturn <BezierEdge {...props} />\n\t}\n\n\tconst { edgeCenterX, edgeCenterY, svgPathString } = getSmartEdgeResponse\n\n\treturn (\n\t\t<>\n\t\t\t<path\n\t\t\t\tstyle={style}\n\t\t\t\tclassName='react-flow__edge-path'\n\t\t\t\td={svgPathString}\n\t\t\t\tmarkerEnd={markerEnd}\n\t\t\t\tmarkerStart={markerStart}\n\t\t\t/>\n\t\t\t<foreignObject\n\t\t\t\twidth={foreignObjectSize}\n\t\t\t\theight={foreignObjectSize}\n\t\t\t\tx={edgeCenterX - foreignObjectSize / 2}\n\t\t\t\ty={edgeCenterY - foreignObjectSize / 2}\n\t\t\t\trequiredExtensions='http://www.w3.org/1999/xhtml'\n\t\t\t>\n\t\t\t\t<button\n\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t\t\talert(`remove ${id}`)\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tX\n\t\t\t\t</button>\n\t\t\t</foreignObject>\n\t\t</>\n\t)\n}\n```\n\n## Advanced Custom Smart Edges\n\nThe `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:\n\n```js\nconst myOptions = {\n\t// your configuration goes here\n\tnodePadding: 20,\n\tgridRatio: 15\n}\n\n// ...\n\nconst getSmartEdgeResponse = getSmartEdge({\n\tsourcePosition,\n\ttargetPosition,\n\tsourceX,\n\tsourceY,\n\ttargetX,\n\ttargetY,\n\tnodes,\n\t// Pass down options in the getSmartEdge object\n\toptions: myOptions\n})\n```\n\nThe `options` object accepts the following keys (they're all optional):\n\n- `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`.\n- `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`.\n- `drawEdge`: Allows you to change the function responsible to draw the SVG line, by default it's the same used by `SmartBezierEdge` ([more below](#drawedge))\n- `generatePath`: Allows you to change the function for the path-finding, by default it's the same used by `SmartBezierEdge` ([more below](#generatepath))\n\n### `drawEdge`\n\nWith the `drawEdge` option, you can change the function used to generate the final [SVG path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths), 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.\n\n```jsx\nimport {\n\tgetSmartEdge,\n\t// Available built-in SVG draw functions\n\tsvgDrawSmoothLinePath,\n\tsvgDrawStraightLinePath\n} from '@jalez/react-flow-smart-edge'\n\n// Using provided SVG draw functions:\nconst result = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tdrawEdge: svgDrawSmoothLinePath\n\t}\n})\n\n// ...or using your own custom function\nconst result = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tdrawEdge: (source, target, path) => {\n\t\t\t// your code goes here\n\t\t\t// ...\n\t\t\treturn svgPath\n\t\t}\n\t}\n})\n```\n\nThe function you provided must comply with this signature:\n\n```ts\ntype SVGDrawFunction = (\n\tsource: XYPosition, // The starting {x, y} point\n\ttarget: XYPosition, // The ending  {x, y} point\n\tpath: number[][] // The sequence of points [x, y] the line must follow\n) => string // A string to be used in the \"d\" property of the SVG line\n```\n\nFor inspiration on how to implement your own, you can check the [`drawSvgPath.ts` source code](https://github.com/tisoap/react-flow-smart-edge/blob/main/src/functions/drawSvgPath.ts).\n\n### `generatePath`\n\nWith the `generatePath` option, you can change the function used to do [Pathfinding](https://en.wikipedia.org/wiki/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](https://www.npmjs.com/package/pathfinding#advanced-usage) behind the scenes.\n\n```jsx\nimport {\n\tgetSmartEdge,\n\t// Available built-in pathfinding functions\n\tpathfindingAStarDiagonal,\n\tpathfindingAStarNoDiagonal,\n\tpathfindingJumpPointNoDiagonal\n} from '@jalez/react-flow-smart-edge'\n\n// Using provided pathfinding functions:\nconst result = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tgeneratePath: pathfindingJumpPointNoDiagonal\n\t}\n})\n\n// ...or using your own custom function\nconst result = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tgeneratePath: (grid, start, end) => {\n\t\t\t// your code goes here\n\t\t\t// ...\n\t\t\treturn { fullPath, smoothedPath }\n\t\t}\n\t}\n})\n```\n\nThe function you provide must comply with this signature:\n\n```ts\ntype PathFindingFunction = (\n\tgrid: Grid, // Grid representation of the graph\n\tstart: XYPosition, // The starting {x, y} point\n\tend: XYPosition // The ending  {x, y} point\n) => {\n\tfullPath: number[][] // Array of points [x, y] representing the full path with all points\n\tsmoothedPath: number[][] // Array of points [x, y] representing a smaller, compressed path\n} | null // The function should return null if it was unable to do pathfinding\n```\n\nFor inspiration on how to implement your own, you can check the [`generatePath.ts` source code](https://github.com/tisoap/react-flow-smart-edge/blob/main/src/functions/generatePath.ts) and the [`pathfinding` dependency](https://www.npmjs.com/package/pathfinding#advanced-usage) documentation.\n\n### Advanced Examples\n\n```jsx\nimport {\n\tgetSmartEdge,\n\tsvgDrawSmoothLinePath,\n\tsvgDrawStraightLinePath\n\tpathfindingAStarDiagonal,\n\tpathfindingAStarNoDiagonal,\n\tpathfindingJumpPointNoDiagonal\n} from '@jalez/react-flow-smart-edge'\n\n// ...\n\n// Same as importing \"SmartBezierEdge\" directly\nconst bezierResult = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tdrawEdge: svgDrawSmoothLinePath,\n\t\tgeneratePath: pathfindingAStarDiagonal,\n\t}\n})\n\n// Same as importing \"SmartStepEdge\" directly\nconst stepResult = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tdrawEdge: svgDrawStraightLinePath,\n\t\tgeneratePath: pathfindingJumpPointNoDiagonal,\n\t}\n})\n\n// Same as importing \"SmartStraightEdge\" directly\nconst straightResult = getSmartEdge({\n\t// ...\n\toptions: {\n\t\tdrawEdge: svgDrawStraightLinePath,\n\t\tgeneratePath: pathfindingAStarNoDiagonal,\n\t}\n})\n```\n\n## Credits & Attribution\n\nThis package is a maintained fork of [@tisoap/react-flow-smart-edge](https://github.com/tisoap/react-flow-smart-edge) by **Tiso Alvarez Puccinelli**.\n\nOriginal project contributors:\n- Tiso Alvarez Puccinelli ([@tisoap](https://github.com/tisoap)) - Original author\n- All [original contributors](https://github.com/tisoap/react-flow-smart-edge/graphs/contributors)\n\n## Community & Support\n\n- 🐛 **Bug reports**: [Open an issue](https://github.com/jalez/react-flow-smart-edge/issues)\n- 💡 **Feature requests**: [Open an issue](https://github.com/jalez/react-flow-smart-edge/issues)\n- 📖 **Documentation**: This README and inline TypeScript types\n- 💬 **Discussions**: [GitHub Discussions](https://github.com/jalez/react-flow-smart-edge/discussions)\n\n## License\n\nThis project is [MIT](LICENSE) licensed, same as the original.\n\nOriginal license: [MIT](https://github.com/tisoap/react-flow-smart-edge/blob/main/LICENSE) by Tiso Alvarez Puccinelli\n","readmeFilename":"README.md","_rev":"1-c83d0045cf58f7c33341ee88d7c469ba"}