diff --git a/connections.js b/connections.js
index 9497061..199ee02 100644
--- a/connections.js
+++ b/connections.js
@@ -7,12 +7,45 @@ export const connectionStyles = css`
.connections path {
transition: stroke 0.3s ease, stroke-width 0.3s ease;
+ pointer-events: all;
+ cursor: pointer;
}
.connections path:hover {
stroke: #999;
stroke-width: 3;
}
+
+ .connections path.selected {
+ stroke: #3498db;
+ stroke-width: 3;
+ }
+
+ .delete-button-group {
+ pointer-events: all;
+ cursor: pointer;
+ }
+
+ .delete-button-group:hover .delete-button-circle {
+ fill: #c0392b;
+ }
+
+ .delete-button-circle {
+ fill: #e74c3c;
+ transition: fill 0.2s ease;
+ }
+
+ .delete-button-x {
+ stroke: white;
+ stroke-width: 2;
+ }
+
+ .delete-button-group {
+ pointer-events: all;
+ cursor: pointer;
+ /* Ensure buttons are always on top of nodes */
+ z-index: 1000;
+ }
`;
export const connections = function(superClass) {
@@ -27,6 +60,12 @@ export const connections = function(superClass) {
firstUpdated() {
this.addEventListener('port-click', this._handlePortClick);
document.addEventListener('mousemove', this._updatePreviewConnection.bind(this));
+ this.canvas.addEventListener('click', (e) => {
+ if (e.target === this.canvas) {
+ this.selectedConnection = null;
+ this.requestUpdate();
+ }
+ });
super.firstUpdated();
}
@@ -130,19 +169,89 @@ export const connections = function(superClass) {
y: end.y
};
+ // Helper function to get point on cubic bezier curve at t (0-1)
+ const getPointOnCurve = (t) => {
+ const t1 = 1 - t;
+ return {
+ x: Math.pow(t1, 3) * start.x +
+ 3 * Math.pow(t1, 2) * t * controlPoint1.x +
+ 3 * t1 * Math.pow(t, 2) * controlPoint2.x +
+ Math.pow(t, 3) * end.x,
+ y: Math.pow(t1, 3) * start.y +
+ 3 * Math.pow(t1, 2) * t * controlPoint1.y +
+ 3 * t1 * Math.pow(t, 2) * controlPoint2.y +
+ Math.pow(t, 3) * end.y
+ };
+ };
+
+ // Get points at 15% and 85% along the curve
+ const startButton = getPointOnCurve(0.15);
+ const endButton = getPointOnCurve(0.85);
+
const path = `M${start.x},${start.y} C${controlPoint1.x},${controlPoint1.y} ${controlPoint2.x},${controlPoint2.y} ${end.x},${end.y}`;
+ const isSelected = this.selectedConnection === conn.id;
return svg`
-
+
+ this._handleConnectionClick(conn.id)}"
+ />
+ ${isSelected ? svg`
+
+
+ this._deleteConnection(conn.id)}">
+
+
+
+
+ this._deleteConnection(conn.id)}">
+
+
+
+
+ ` : ''}
+
`;
}
+ _handleConnectionClick(connectionId) {
+ // Deselect if clicking the same connection
+ if (this.selectedConnection === connectionId) {
+ this.selectedConnection = null;
+ } else {
+ this.selectedConnection = connectionId;
+ }
+ this.requestUpdate();
+ }
+
+ _deleteConnection(connectionId) {
+ this.connections = this.connections.filter(conn => conn.id !== connectionId);
+ this.selectedConnection = null;
+ this.requestUpdate();
+ }
+
_handlePortClick(e) {
const { nodeId, portType, portId, portName } = e.detail;
diff --git a/panning.js b/panning.js
index 29e474c..19ab50f 100644
--- a/panning.js
+++ b/panning.js
@@ -29,11 +29,11 @@ export const panning = function(superClass) {
}
firstUpdated() {
- super.firstUpdated();
this.canvas = this.shadowRoot.querySelector('.canvas');
this.addEventListener('mousedown', this._startDrag.bind(this));
document.addEventListener('mousemove', this._drag.bind(this));
document.addEventListener('mouseup', this._endDrag.bind(this));
+ super.firstUpdated();
}
_getTopNodeAtPoint(x, y) {