This commit is contained in:
2024-12-20 10:29:39 +01:00
parent a892e1fcb2
commit 5e449e23b8
5 changed files with 313 additions and 34 deletions

View File

@@ -60,12 +60,39 @@ export const connections = function(superClass) {
firstUpdated() {
this.addEventListener('port-click', this._handlePortClick);
document.addEventListener('mousemove', this._updatePreviewConnection.bind(this));
this.canvas.addEventListener('click', (e) => {
document.addEventListener('click', (e) => {
// Check if clicking on an output port
const path = e.composedPath();
const isOutputPort = path.some(el =>
el instanceof HTMLElement &&
el.classList &&
el.classList.contains('output-ports')
);
// Only cancel connection if we're dragging AND it's not an output port
if (this.draggingConnection && !isOutputPort) {
// Check if we clicked on an input port
const isInputPort = path.some(el =>
el instanceof HTMLElement &&
el.classList &&
el.classList.contains('input-ports')
);
// If not an input port, cancel the connection
if (!isInputPort) {
this.draggingConnection = null;
this.requestUpdate();
}
}
// Handle existing connection deselection
if (e.target === this.canvas) {
this.selectedConnection = null;
this.requestUpdate();
}
});
super.firstUpdated();
}
@@ -80,8 +107,31 @@ export const connections = function(superClass) {
}
_renderConnections() {
const bounds = this._calculateSVGBounds();
// Handle initial render when canvas is not ready
const style = this.canvas ? `
position: absolute;
top: ${bounds.minY}px;
left: ${bounds.minX}px;
width: ${bounds.width}px;
height: ${bounds.height}px;
pointer-events: none;
` : `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
`;
return html`
<svg class="connections" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;">
<svg
class="connections"
style="${style}"
viewBox="${this.canvas ? `${bounds.minX} ${bounds.minY} ${bounds.width} ${bounds.height}` : '0 0 100 100'}"
>
${this.connections.map(conn => this._renderConnection(conn))}
${this.draggingConnection ? this._renderPreviewConnection() : null}
</svg>
@@ -138,7 +188,7 @@ export const connections = function(superClass) {
const sourceNode = this.nodes.find(node => node.id === conn.sourceNodeId);
const targetNode = this.nodes.find(node => node.id === conn.targetNodeId);
if (!sourceNode || !targetNode) return '';
if (!sourceNode?.shadowRoot || !targetNode?.shadowRoot) return '';
const sourcePort = sourceNode.shadowRoot.querySelector(`.output-ports [data-port-id="${conn.sourcePortId}"]`);
const targetPort = targetNode.shadowRoot.querySelector(`.input-ports [data-port-id="${conn.targetPortId}"]`);
@@ -247,8 +297,17 @@ export const connections = function(superClass) {
}
_deleteConnection(connectionId) {
const connection = this.connections.find(conn => conn.id === connectionId);
this.connections = this.connections.filter(conn => conn.id !== connectionId);
this.selectedConnection = null;
if (connection) {
this._dispatchChangeEvent({
type: 'connection-removed',
data: { connectionId }
});
}
this.requestUpdate();
}
@@ -282,11 +341,48 @@ export const connections = function(superClass) {
};
this.connections = [...this.connections, connection];
this._dispatchChangeEvent({
type: 'connection-added',
data: connection
});
}
}
this.draggingConnection = null;
this.requestUpdate();
}
}
_calculateSVGBounds() {
// If canvas is not ready yet, return default bounds
if (!this.canvas) {
return {
minX: 0,
minY: 0,
width: '100%',
height: '100%'
};
}
let minX = 0, minY = 0, maxX = 0, maxY = 0;
const canvasRect = this.canvas.getBoundingClientRect();
// Include all node positions
this.nodes.forEach(node => {
const rect = node.getBoundingClientRect();
minX = Math.min(minX, (rect.left - canvasRect.left) / this.scale);
minY = Math.min(minY, (rect.top - canvasRect.top) / this.scale);
maxX = Math.max(maxX, (rect.right - canvasRect.left) / this.scale);
maxY = Math.max(maxY, (rect.bottom - canvasRect.top) / this.scale);
});
const padding = 1000;
return {
minX: minX - padding,
minY: minY - padding,
width: maxX - minX + (padding * 2),
height: maxY - minY + (padding * 2)
};
}
};
}