
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
node-link-utils
Advanced tools
A pure JavaScript visual node connector for creating draggable connections between nodes. Framework-agnostic and easy to use
A pure JavaScript visual node connector for creating draggable connections between nodes. Framework-agnostic and easy to use.

npm install node-link-utils
Or using yarn:
yarn add node-link-utils
Or using pnpm:
pnpm add node-link-utils
import Connector from "node-link-utils";
// 1. Get container element
const container = document.getElementById("connector-container");
// 2. Create connector instance
const connector = new Connector({
container: container,
// Optional configuration
lineColor: "#155BD4",
lineWidth: 2,
dotSize: 12,
dotColor: "#155BD4",
// Event callbacks
onConnect: (connection) => {
console.log("Connection created:", connection);
// connection: { from: 'node1', to: 'node2', fromDot: 'right', toDot: 'left' }
},
onDisconnect: (connection) => {
console.log("Connection removed:", connection);
}
});
// 3. Register nodes
const node1 = document.getElementById("node1");
const node2 = document.getElementById("node2");
connector.registerNode("node1", node1, {
dotPositions: ["right"] // Only right connection dot
});
connector.registerNode("node2", node2, {
dotPositions: ["left", "right"] // Both left and right dots
});
<div
id="connector-container"
style="position: relative; height: 600px;"
>
<div
id="node1"
style="position: absolute; left: 100px; top: 100px;"
>
Node 1
</div>
<div
id="node2"
style="position: absolute; left: 400px; top: 100px;"
>
Node 2
</div>
</div>
| Option | Type | Default | Description |
|---|---|---|---|
container | HTMLElement | Required | Container element for the connector |
lineColor | String | '#155BD4' | Color of connection lines |
lineWidth | Number | 2 | Width of connection lines |
dotSize | Number | 12 | Size of connection dots |
dotColor | String | '#155BD4' | Color of connection dots |
deleteButtonSize | Number | 20 | Size of delete button |
enableNodeDrag | Boolean | true | Enable node dragging |
enableSnap | Boolean | true | Enable connection snapping |
snapDistance | Number | 20 | Snap distance in pixels |
onConnect | Function | () => {} | Callback when connection is created |
onDisconnect | Function | () => {} | Callback when connection is removed |
registerNode(id, element, options)Register a node for connection.
Parameters:
id (String): Unique identifier for the nodeelement (HTMLElement): DOM element of the nodeoptions (Object): Node configuration
dotPositions (String | Array): Connection dot positions
'both': Both left and right dots['left', 'right']: Array format, both sides['left']: Only left dot['right']: Only right dotReturns: Node object
Example:
connector.registerNode("myNode", element, {
dotPositions: ["right"]
});
createConnection(fromNode, toNode, fromDot, toDot)Programmatically create a connection between nodes.
Parameters:
fromNode (Object): Source node objecttoNode (Object): Target node objectfromDot (Object): Source connection dot (optional)toDot (Object): Target connection dot (optional)Returns: Connection object
Example:
const node1 = connector.nodes[0];
const node2 = connector.nodes[1];
connector.createConnection(node1, node2);
disconnect(connectionId)Remove a connection.
Parameters:
connectionId (String): Connection ID (optional, if not provided, removes all connections)Example:
connector.disconnect(); // Remove all connections
connector.disconnect("connection-id"); // Remove specific connection
getConnections()Get all connections.
Returns: Array of connection information
Example:
const connections = connector.getConnections();
// [{ id: '...', from: 'node1', to: 'node2', fromDot: 'right', toDot: 'left' }]
getNodeConnections(nodeId)Get all connections for a specific node.
Parameters:
nodeId (String): Node IDReturns: Array of connection information
updateNodePosition(nodeId)Update node position (called when node is moved).
Parameters:
nodeId (String): Node IDdestroy()Destroy the connector and clean up all resources.
Example:
connector.destroy();
<template>
<div
class="container"
ref="containerRef"
>
<div
class="node"
ref="node1Ref"
>
Node 1
</div>
<div
class="node"
ref="node2Ref"
>
Node 2
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import Connector from "node-link-utils";
const containerRef = ref(null);
const node1Ref = ref(null);
const node2Ref = ref(null);
let connector = null;
onMounted(() => {
connector = new Connector({
container: containerRef.value,
onConnect: (connection) => {
console.log("Connection created:", connection);
},
onDisconnect: (connection) => {
console.log("Connection removed:", connection);
}
});
connector.registerNode("node1", node1Ref.value, {
dotPositions: ["right"]
});
connector.registerNode("node2", node2Ref.value, {
dotPositions: ["left"]
});
});
onBeforeUnmount(() => {
if (connector) {
connector.destroy();
}
});
</script>
<style scoped>
.container {
position: relative;
height: 600px;
background: #f5f5f5;
}
.node {
position: absolute;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
cursor: move;
}
</style>
import { useEffect, useRef } from "react";
import Connector from "node-link-utils";
function App() {
const containerRef = useRef(null);
const node1Ref = useRef(null);
const node2Ref = useRef(null);
const connectorRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
connectorRef.current = new Connector({
container: containerRef.current,
onConnect: (connection) => {
console.log("Connection created:", connection);
},
onDisconnect: (connection) => {
console.log("Connection removed:", connection);
}
});
connectorRef.current.registerNode("node1", node1Ref.current, {
dotPositions: ["right"]
});
connectorRef.current.registerNode("node2", node2Ref.current, {
dotPositions: ["left"]
});
return () => {
if (connectorRef.current) {
connectorRef.current.destroy();
}
};
}, []);
return (
<div
ref={containerRef}
style={{ position: "relative", height: "600px" }}
>
<div
ref={node1Ref}
style={{ position: "absolute", left: "100px", top: "100px" }}
>
Node 1
</div>
<div
ref={node2Ref}
style={{ position: "absolute", left: "400px", top: "100px" }}
>
Node 2
</div>
</div>
);
}
<!DOCTYPE html>
<html>
<head>
<style>
#container {
position: relative;
height: 600px;
background: #f5f5f5;
}
.node {
position: absolute;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
cursor: move;
}
</style>
</head>
<body>
<div id="container">
<div
id="node1"
class="node"
style="left: 100px; top: 100px;"
>
Node 1
</div>
<div
id="node2"
class="node"
style="left: 400px; top: 100px;"
>
Node 2
</div>
</div>
<script type="module">
import Connector from "node-link-utils";
const connector = new Connector({
container: document.getElementById("container"),
onConnect: (connection) => {
console.log("Connection created:", connection);
}
});
connector.registerNode("node1", document.getElementById("node1"), {
dotPositions: ["right"]
});
connector.registerNode("node2", document.getElementById("node2"), {
dotPositions: ["left"]
});
</script>
</body>
</html>
// Node with both left and right connection points
connector.registerNode("centerNode", element, {
dotPositions: ["left", "right"]
});
// Node with only left connection point
connector.registerNode("endNode", element, {
dotPositions: ["left"]
});
// Node with only right connection point
connector.registerNode("startNode", element, {
dotPositions: ["right"]
});
const connector = new Connector({
container: container,
lineColor: "#FF6B6B", // Red connections
lineWidth: 3, // Thicker lines
dotSize: 16, // Larger dots
dotColor: "#4ECDC4", // Teal dots
deleteButtonSize: 24 // Larger delete button
});
const connector = new Connector({
container: container,
onConnect: (connection) => {
console.log("New connection:", connection);
// { from: 'node1', to: 'node2', fromDot: 'right', toDot: 'left' }
// Save to database, update state, etc.
saveConnection(connection);
},
onDisconnect: (connection) => {
console.log("Connection removed:", connection);
// Update database, state, etc.
removeConnection(connection);
}
});
MIT License
Contributions, issues and feature requests are welcome!
If you have any questions or need help, please open an issue on GitHub.
Give a ⭐️ if this project helped you!
Made with ❤️ by the node-link-utils team
FAQs
A pure JavaScript visual node connector for creating draggable connections between nodes. Framework-agnostic and easy to use
We found that node-link-utils demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.