From 7c2a768d833ff942b4dc8e162c3f680bd3df6acc Mon Sep 17 00:00:00 2001 From: AustinMroz Date: Tue, 4 Nov 2025 13:45:14 -0800 Subject: [PATCH] More forgiving connections in vue (#6565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous link connection code uses [closest](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest) to find a slot. Closest only checks parents, not siblings. Since the sought element has no children, this meant connection to a slot required the mouse be directly over the slot. This is changed by finding the closest (parent) widget or slot, and then querying for the slot. For simplicity, this means introducing an `lg-node-widget` class. As a result, connections can be made by hovering anywhere over a valid widget. ![vue-connections_00001](https://github.com/user-attachments/assets/e556ff3f-8cbb-4198-998d-9c2aadf2c73c) Resolves #6488 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6565-More-forgiving-connections-in-vue-2a16d73d365081e1bf46f5d54ec382d6) by [Unito](https://www.unito.io) --- .../core/canvas/links/linkDropOrchestrator.ts | 4 +++- .../vueNodes/components/NodeWidgets.vue | 2 +- .../composables/useSlotLinkInteraction.ts | 21 ++++++++----------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/renderer/core/canvas/links/linkDropOrchestrator.ts b/src/renderer/core/canvas/links/linkDropOrchestrator.ts index 086a2dc8b..6e3fec991 100644 --- a/src/renderer/core/canvas/links/linkDropOrchestrator.ts +++ b/src/renderer/core/canvas/links/linkDropOrchestrator.ts @@ -20,7 +20,9 @@ export const resolveSlotTargetCandidate = ( const { state: dragState, setCompatibleForKey } = useSlotLinkDragUIState() if (!(target instanceof HTMLElement)) return null - const elWithKey = target.closest('[data-slot-key]') + const elWithKey = target + .closest('.lg-slot, .lg-node-widget') + ?.querySelector('[data-slot-key]') const key = elWithKey?.dataset['slotKey'] if (!key) return null diff --git a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue index 18fe8cc56..f843897e3 100644 --- a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue +++ b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue @@ -19,7 +19,7 @@
diff --git a/src/renderer/extensions/vueNodes/composables/useSlotLinkInteraction.ts b/src/renderer/extensions/vueNodes/composables/useSlotLinkInteraction.ts index f93885e88..3baf2b047 100644 --- a/src/renderer/extensions/vueNodes/composables/useSlotLinkInteraction.ts +++ b/src/renderer/extensions/vueNodes/composables/useSlotLinkInteraction.ts @@ -301,14 +301,12 @@ export function useSlotLinkInteraction({ hoveredSlotKey = dragContext.lastPointerTargetSlotKey hoveredNodeId = dragContext.lastPointerTargetNodeId } else if (target instanceof HTMLElement) { - const elWithSlot = target.closest('[data-slot-key]') - const elWithNode = elWithSlot - ? null - : target.closest('[data-node-id]') + const elWithSlot = target + .closest('.lg-slot, .lg-node-widget') + ?.querySelector('[data-slot-key]') + const elWithNode = target.closest('[data-node-id]') hoveredSlotKey = elWithSlot?.dataset['slotKey'] ?? null - hoveredNodeId = hoveredSlotKey - ? null - : (elWithNode?.dataset['nodeId'] ?? null) + hoveredNodeId = elWithNode?.dataset['nodeId'] ?? null dragContext.lastPointerEventTarget = target dragContext.lastPointerTargetSlotKey = hoveredSlotKey dragContext.lastPointerTargetNodeId = hoveredNodeId @@ -325,10 +323,8 @@ export function useSlotLinkInteraction({ const graph = app.canvas?.graph ?? null const context = { adapter, graph, session: dragContext } const slotCandidate = resolveSlotTargetCandidate(target, context) - const nodeCandidate = slotCandidate - ? null - : resolveNodeSurfaceSlotCandidate(target, context) - candidate = slotCandidate ?? nodeCandidate + const nodeCandidate = resolveNodeSurfaceSlotCandidate(target, context) + candidate = slotCandidate?.compatible ? slotCandidate : nodeCandidate dragContext.lastHoverSlotKey = hoveredSlotKey dragContext.lastHoverNodeId = hoveredNodeId @@ -339,7 +335,8 @@ export function useSlotLinkInteraction({ slotCandidate.layout.type === 'input' ) setCompatibleForKey(key, !!slotCandidate.compatible) - } else if (nodeCandidate) { + } + if (nodeCandidate && !slotCandidate?.compatible) { const key = getSlotKey( nodeCandidate.layout.nodeId, nodeCandidate.layout.index,