Skip to content

Commit 3d1b85f

Browse files
committed
refactor(core): allow setting handleId in useNodeConnections (#1732)
* refactor(core): allow setting handleId in useNodeConnections Signed-off-by: braks <[email protected]> * chore(core): deprecate useHandleConnections Signed-off-by: braks <[email protected]> * chore(examples): cleanup Signed-off-by: braks <[email protected]> * chore(docs): cleanup Signed-off-by: braks <[email protected]> * chore(core): cleanup Signed-off-by: braks <[email protected]> * chore(core): cleanup Signed-off-by: braks <[email protected]> * chore(docs): cleanup Signed-off-by: braks <[email protected]> --------- Signed-off-by: braks <[email protected]>
1 parent 268ed0e commit 3d1b85f

File tree

12 files changed

+122
-114
lines changed

12 files changed

+122
-114
lines changed

docs/examples/custom-node/OutputNode.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup>
2-
import { Handle, Position, useHandleConnections, useNodesData } from '@vue-flow/core'
2+
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'
33
4-
const connections = useHandleConnections({
4+
const connections = useNodeConnections({
55
type: 'target',
66
})
77

docs/examples/layout/ProcessNode.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup>
22
import { computed, toRef } from 'vue'
3-
import { Handle, useHandleConnections } from '@vue-flow/core'
3+
import { Handle, useNodeConnections } from '@vue-flow/core'
44
55
const props = defineProps({
66
data: {
@@ -15,11 +15,11 @@ const props = defineProps({
1515
},
1616
})
1717
18-
const sourceConnections = useHandleConnections({
18+
const sourceConnections = useNodeConnections({
1919
type: 'target',
2020
})
2121
22-
const targetConnections = useHandleConnections({
22+
const targetConnections = useNodeConnections({
2323
type: 'source',
2424
})
2525

docs/examples/math/ResultNode.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup>
22
import { computed } from 'vue'
3-
import { Handle, Position, useHandleConnections, useNodeConnections, useNodesData } from '@vue-flow/core'
3+
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'
44
55
defineProps(['id'])
66
@@ -12,7 +12,7 @@ const mathFunctions = {
1212
}
1313
1414
// Get the source connections of the result node. In this example it's only one operator node.
15-
const sourceConnections = useHandleConnections({
15+
const sourceConnections = useNodeConnections({
1616
// type target means all connections where *this* node is the target
1717
// that means we go backwards in the graph to find the source of the connection(s)
1818
type: 'target',
@@ -49,7 +49,6 @@ const result = computed(() => {
4949
</script>
5050
5151
<template>
52-
{{ operatorSourceConnections }}
5352
<div class="calculation">
5453
<template v-for="(value, i) in valueData" :key="`${value.id}-${value.data}`">
5554
<span>

docs/src/examples/math.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Math Operation
22

3-
This example demonstrates how to use the different composables like `useHandleConnections` or `useNodesData` to create a data flow between nodes.
3+
This example demonstrates how to use the different composables like `useNodeConnections` or `useNodesData` to create a data flow between nodes.
44

5-
In this example we use nodes to create a simple math operation, where the user can input two numbers and select an operation to perform.
5+
We use nodes to create a simple math operation, where the user can input two numbers and select an operation to perform.
66

77
<div class="mt-6">
88
<Repl example="math"></Repl>

docs/src/guide/composables.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ const connections = useHandleConnections({
102102
## [useNodeConnections](/typedocs/functions/useNodeConnections)
103103

104104
`useNodeConnections` provides you with an array of connections that are connected to a specific node.
105-
This composable is especially useful when you want to get all connections (of either type `source` or `target`) of a node
106-
instead of just the connections of a specific `<Handle>`.
105+
This composable is especially useful when you want to get all connections (of either type `source` or `target`) of a node.
107106

108107
```ts
109108
import { type HandleConnection, useNodeConnections } from '@vue-flow/core'
@@ -119,6 +118,10 @@ const sourceConnections = useNodeConnections({
119118
type: 'source',
120119
})
121120

121+
const handleConnections = useNodeConnections({
122+
handleId: 'handle-1', // you can explicitly pass a handle id if you want to get connections of a specific handle
123+
})
124+
122125
const connections = useNodeConnections({
123126
nodeId: '1', // you can explicitly pass a node id, otherwise it's used from the `NodeId injection
124127
type: 'target',

examples/vite/src/Layouting/ProcessNode.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
<script setup lang="ts">
22
import type { NodeProps } from '@vue-flow/core'
3-
import { Handle, useHandleConnections } from '@vue-flow/core'
3+
import { Handle, useNodeConnections } from '@vue-flow/core'
44
import type { ProcessNodeData } from './types'
55
66
const props = defineProps<NodeProps<ProcessNodeData>>()
77
8-
const sourceConnections = useHandleConnections({
8+
const sourceConnections = useNodeConnections({
99
type: 'target',
1010
})
1111
12-
const targetConnections = useHandleConnections({
12+
const targetConnections = useNodeConnections({
1313
type: 'source',
1414
})
1515

examples/vite/src/Math/ResultNode.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script setup lang="ts">
22
import type { GraphNode } from '@vue-flow/core'
3-
import { Handle, Position, useHandleConnections, useNodeConnections, useNodesData } from '@vue-flow/core'
3+
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'
44
import type { OperatorNodeData, ValueNodeData } from './types'
55
import { mathFunctions } from './utils'
66
77
defineProps<{ id: string }>()
88
99
// Get the source connections of the result node. In this example it's only one operator node.
10-
const sourceConnections = useHandleConnections({
10+
const sourceConnections = useNodeConnections({
1111
// type target means all connections where *this* node is the target
1212
// that means we go backwards in the graph to find the source of the connection(s)
1313
type: 'target',

packages/core/src/composables/useHandleConnections.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface UseHandleConnectionsParams {
1616
/**
1717
* Composable that returns existing connections of a `<Handle />`.
1818
*
19+
* @deprecated use `useNodeConnections` instead
1920
* @public
2021
* @param params
2122
* @param params.type - handle type `source` or `target`
Lines changed: 37 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,80 @@
1-
import type { ComputedRef, MaybeRefOrGetter } from 'vue'
2-
import { computed, ref, toRef, toValue, watch } from 'vue'
3-
import type { HandleConnection, HandleElement, HandleType } from '../types'
1+
import type { MaybeRefOrGetter } from 'vue'
2+
import { computed, ref, toValue, watch } from 'vue'
3+
import type { HandleType, NodeConnection } from '../types'
4+
import { areConnectionMapsEqual, handleConnectionChange } from '../utils'
45
import { useNodeId } from './useNodeId'
56
import { useVueFlow } from './useVueFlow'
67

78
export interface UseNodeConnectionsParams {
8-
type: MaybeRefOrGetter<HandleType>
9+
type?: MaybeRefOrGetter<HandleType>
10+
handleId?: MaybeRefOrGetter<string | null>
911
nodeId?: MaybeRefOrGetter<string | null>
10-
onConnect?: (connections: HandleConnection[]) => void
11-
onDisconnect?: (connections: HandleConnection[]) => void
12+
onConnect?: (connections: NodeConnection[]) => void
13+
onDisconnect?: (connections: NodeConnection[]) => void
1214
}
1315

1416
/**
15-
* Composable that returns existing connections of a node by handle type.
16-
* This is useful when you want to get all connections of a node by a specific handle type.
17+
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
1718
*
1819
* @public
1920
* @param params
2021
* @param params.type - handle type `source` or `target`
2122
* @param params.nodeId - node id - if not provided, the node id from the `useNodeId` (meaning, the context-based injection) is used
23+
* @param params.handleId - the handle id (this is required if the node has multiple handles of the same type)
2224
* @param params.onConnect - gets called when a connection is created
2325
* @param params.onDisconnect - gets called when a connection is removed
2426
*
2527
* @returns An array of connections
2628
*/
27-
export function useNodeConnections(params: UseNodeConnectionsParams): ComputedRef<HandleConnection[]> {
28-
const { type, nodeId, onConnect, onDisconnect } = params
29+
export function useNodeConnections(params: UseNodeConnectionsParams = {}) {
30+
const { type, handleId, nodeId, onConnect, onDisconnect } = params
2931

30-
const { connectionLookup, findNode } = useVueFlow()
32+
const { connectionLookup } = useVueFlow()
3133

3234
const _nodeId = useNodeId()
3335

34-
const currentNodeId = toRef(() => toValue(nodeId) ?? _nodeId)
36+
const prevConnections = ref<Map<string, NodeConnection> | null>(null)
3537

36-
const handleType = toRef(() => toValue(type))
38+
const connections = ref<Map<string, NodeConnection>>()
3739

38-
const node = computed(() => findNode(currentNodeId.value))
40+
const lookupKey = computed(() => {
41+
const currNodeId = toValue(nodeId) ?? _nodeId
42+
const handleType = toValue(type)
43+
const currHandleId = toValue(handleId)
3944

40-
const handleIds = computed(() => {
41-
if (!node.value) {
42-
return []
43-
}
44-
45-
const handles: HandleElement['id'][] = []
46-
for (const handle of node.value?.handleBounds?.[handleType.value] ?? []) {
47-
handles.push(handle.id)
48-
}
49-
50-
return handles
51-
})
52-
53-
const prevConnections = ref<Map<string, HandleConnection> | null>(null)
54-
55-
const connectionsFromLookup = computed(() => {
56-
const nodeConnections = [] as Map<string, HandleConnection>[]
57-
58-
for (const handleId of handleIds.value) {
59-
const connectionMap = connectionLookup.value.get(`${currentNodeId.value}-${handleType.value}-${handleId}`)
60-
if (connectionMap) {
61-
nodeConnections.push(connectionMap)
62-
}
63-
}
64-
65-
return nodeConnections
45+
return `${currNodeId}${handleType ? (currHandleId ? `-${handleType}-${currHandleId}` : `-${handleType}`) : ''}`
6646
})
6747

6848
watch(
69-
[connectionsFromLookup, () => typeof onConnect !== 'undefined', () => typeof onDisconnect !== 'undefined'],
70-
([currentConnections]) => {
71-
if (!currentConnections) {
49+
() => connectionLookup.value.get(lookupKey.value),
50+
(nextConnections) => {
51+
if (areConnectionMapsEqual(connections.value, nextConnections)) {
7252
return
7353
}
7454

75-
const newConnections = new Map<string, HandleConnection>()
76-
77-
for (const connectionMap of currentConnections) {
78-
for (const [key, connection] of connectionMap) {
79-
newConnections.set(key, connection)
80-
}
81-
}
82-
83-
if (!prevConnections.value) {
84-
prevConnections.value = new Map(newConnections)
85-
return
86-
}
87-
88-
const prevConnectionsValue = prevConnections.value
89-
90-
const addedConnections = Array.from(newConnections.keys()).filter((key) => !prevConnectionsValue.has(key))
91-
92-
const removedConnections = Array.from(prevConnectionsValue.keys()).filter((key) => !newConnections.has(key))
93-
94-
if (addedConnections.length && onConnect) {
95-
const added = addedConnections.map((key) => newConnections.get(key)!)
96-
onConnect(added)
97-
}
55+
connections.value = nextConnections
56+
},
57+
{ immediate: true },
58+
)
9859

99-
if (removedConnections.length && onDisconnect) {
100-
const removed = removedConnections.map((key) => prevConnectionsValue.get(key)!)
101-
onDisconnect(removed)
60+
watch(
61+
[connections, () => typeof onConnect !== 'undefined', () => typeof onDisconnect !== 'undefined'],
62+
([currentConnections = new Map<string, NodeConnection>()]) => {
63+
if (prevConnections.value && prevConnections.value !== currentConnections) {
64+
handleConnectionChange(prevConnections.value, currentConnections, onDisconnect)
65+
handleConnectionChange(currentConnections, prevConnections.value, onConnect)
10266
}
10367

104-
prevConnections.value = new Map(newConnections)
68+
prevConnections.value = currentConnections
10569
},
10670
{ immediate: true },
10771
)
10872

10973
return computed(() => {
110-
const connections = [] as HandleConnection[]
111-
112-
for (const connectionMap of connectionsFromLookup.value) {
113-
for (const connection of connectionMap.values()) {
114-
connections.push(connection)
115-
}
74+
if (!connections.value) {
75+
return []
11676
}
11777

118-
return connections
78+
return Array.from(connections.value.values())
11979
})
12080
}

packages/core/src/store/actions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ export function useActions(state: State, nodeLookup: ComputedRef<NodeLookup>, ed
349349
state.edges,
350350
)
351351

352-
updateConnectionLookup(state.connectionLookup, validEdges)
352+
updateConnectionLookup(state.connectionLookup, edgeLookup.value, validEdges)
353353

354354
state.edges = validEdges
355355
}
@@ -527,7 +527,7 @@ export function useActions(state: State, nodeLookup: ComputedRef<NodeLookup>, ed
527527

528528
state.edges.splice(state.edges.indexOf(prevEdge), 1, validEdge)
529529

530-
updateConnectionLookup(state.connectionLookup, [validEdge])
530+
updateConnectionLookup(state.connectionLookup, edgeLookup.value, [validEdge])
531531

532532
return validEdge
533533
}
@@ -554,7 +554,7 @@ export function useActions(state: State, nodeLookup: ComputedRef<NodeLookup>, ed
554554
const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) => {
555555
const changedEdges = applyChanges(changes, state.edges)
556556

557-
updateConnectionLookup(state.connectionLookup, changedEdges)
557+
updateConnectionLookup(state.connectionLookup, edgeLookup.value, changedEdges)
558558

559559
return changedEdges
560560
}

0 commit comments

Comments
 (0)