Support `placeNewNodes` from `cytoscape-layout-utilities`
I have a dynamic graph, where nodes can be added and removed. When adding nodes to an existing graph, I'd like to use the placeNewNodes function from cytoscape-layout-utilities.
The following recording of the cytoscape-layout-utilities demo site shows how placeNewNodes results in a good "incremental" layout, by taking into account the positions of the existing nodes.
https://github.com/user-attachments/assets/e31826fd-675c-4d7e-a2fc-ea37d8a717b3
To use placeNewNodes, you basically need to follow these steps:
// 1. Init the extension.
const layoutUtils = cy.layoutUtilities({
// config options if needed...
});
// 2. Add the new nodes and edges to the graph.
const newEles = cy.add([
// Dummy data for the sake of an example
{ group: "nodes", data: { id: "new-node-id" } },
{
group: "edges",
data: {
id: "new-edge-id",
source: "some-node-id",
target: "other-node-id",
},
},
]);
const newNodes = newEles.nodes();
// 3. Use the extension to determine appropriate node positions.
layoutUtils.placeNewNodes(newNodes);
// 4. Run the layout to move the nodes to the positions determined by the extension.
cy.layout({
name: "fcose",
randomize: false,
fit: true,
animationDuration: 1_000,
}).run();
But here's the problem: With react-cytoscapejs, consumers don't have a way of calling cy.placeNewNodes between the cy.add and cy.layout invocations. Consumers need a way to "hook into" the patching lifecycle.
1 possible solution would be to add a prop like onElementsPatched to CytoscapeComponent. If specified, onElementsPatched could be called after patchElements runs here:
https://github.com/plotly/react-cytoscapejs/blob/a947bab8e28f4444620e3c03286892eee46b42ed/src/patch.js#L16
That way, consumers could run placeNewNodes (or whatever logic) before this library runs the layout again.
If you'd be open to this, I'd be happy to contribute a PR!
I'm applying to solve the issue of enabling incremental graph layouts in react-cytoscapejs using placeNewNodes from cytoscape-layout-utilities. My solution involves adding an onElementsPatched prop to allow users to run layout-related logic before the default layout triggers. With experience in Cytoscape.js and React, I can implement this feature cleanly and improve dynamic graph handling for developers.