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` - + + + ${isSelected ? svg` + + + + + + + + + + + + + ` : ''} + `; } + _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) {