Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: next release #1729

Merged
merged 7 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/examples/custom-node/OutputNode.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup>
import { Handle, Position, useHandleConnections, useNodesData } from '@vue-flow/core'
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'

const connections = useHandleConnections({
type: 'target',
const connections = useNodeConnections({
handleType: 'target',
})

const nodesData = useNodesData(() => connections.value[0]?.source)
Expand Down
10 changes: 5 additions & 5 deletions docs/examples/layout/ProcessNode.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { computed, toRef } from 'vue'
import { Handle, useHandleConnections } from '@vue-flow/core'
import { Handle, useNodeConnections } from '@vue-flow/core'

const props = defineProps({
data: {
Expand All @@ -15,12 +15,12 @@ const props = defineProps({
},
})

const sourceConnections = useHandleConnections({
type: 'target',
const sourceConnections = useNodeConnections({
handleType: 'target',
})

const targetConnections = useHandleConnections({
type: 'source',
const targetConnections = useNodeConnections({
handleType: 'source',
})

const isSender = toRef(() => sourceConnections.value.length <= 0)
Expand Down
15 changes: 7 additions & 8 deletions docs/examples/math/ResultNode.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { computed } from 'vue'
import { Handle, Position, useHandleConnections, useNodesData, useVueFlow } from '@vue-flow/core'
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'

defineProps(['id'])

Expand All @@ -11,19 +11,18 @@ const mathFunctions = {
'/': (a, b) => a / b,
}

const { getConnectedEdges } = useVueFlow()

// Get the source connections of the result node. In this example it's only one operator node.
const sourceConnections = useHandleConnections({
const sourceConnections = useNodeConnections({
// type target means all connections where *this* node is the target
// that means we go backwards in the graph to find the source of the connection(s)
type: 'target',
handleType: 'target',
})

// Get the source connections of the operator node
const operatorSourceConnections = computed(() =>
getConnectedEdges(sourceConnections.value[0].source).filter((e) => e.source !== sourceConnections.value[0].source),
)
const operatorSourceConnections = useNodeConnections({
handleType: 'target',
nodeId: () => sourceConnections.value[0]?.source,
})

const operatorData = useNodesData(() => sourceConnections.value.map((connection) => connection.source))

Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples/math.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Math Operation

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

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.
We use nodes to create a simple math operation, where the user can input two numbers and select an operation to perform.

<div class="mt-6">
<Repl example="math"></Repl>
Expand Down
44 changes: 40 additions & 4 deletions docs/src/guide/composables.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,14 @@ onInit((instance) => {

## [useHandleConnections](/typedocs/functions/useHandleConnections)

`useHandleConnections` provides you with an array of connections that are connected to the node you pass to it.
`useHandleConnections` provides you with an array of connections that are connected to specific `<Handle>`.

```ts
import { useHandleConnections } from '@vue-flow/core'
import { type HandleConnection, useHandleConnections } from '@vue-flow/core'

// get all connections where this node is the target (incoming connections)
const targetConnections = useHandleConnections({
// type is required
type: 'target',
})

Expand All @@ -89,10 +90,45 @@ const connections = useHandleConnections({
id: 'handle-1', // you can explicitly pass a handle id if there are multiple handles of the same type
nodeId: '1', // you can explicitly pass a node id, otherwise it's used from the `NodeId injection
type: 'target',
onConnect: (connections: Connection[]) => {
onConnect: (connections: HandleConnection[]) => {
// do something with the connections
},
onDisconnect: (connections: Connection[]) => {
onDisconnect: (connections: HandleConnection[]) => {
// do something with the connections
},
})
```

## [useNodeConnections](/typedocs/functions/useNodeConnections)

`useNodeConnections` provides you with an array of connections that are connected to a specific node.
This composable is especially useful when you want to get all connections (of either type `source` or `target`) of a node.

```ts
import { type HandleConnection, useNodeConnections } from '@vue-flow/core'

// get all connections where this node is the target (incoming connections)
const targetConnections = useNodeConnections({
// type is required
handleType: 'target',
})

// get all connections where this node is the source (outgoing connections)
const sourceConnections = useNodeConnections({
handleType: 'source',
})

const handleConnections = useNodeConnections({
handleId: 'handle-1', // you can explicitly pass a handle id if you want to get connections of a specific handle
})

const connections = useNodeConnections({
nodeId: '1', // you can explicitly pass a node id, otherwise it's used from the `NodeId injection
handleType: 'target',
onConnect: (connections: HandleConnection[]) => {
// do something with the connections
},
onDisconnect: (connections: HandleConnection[]) => {
// do something with the connections
},
})
Expand Down
10 changes: 5 additions & 5 deletions examples/vite/src/Layouting/ProcessNode.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<script setup lang="ts">
import type { NodeProps } from '@vue-flow/core'
import { Handle, useHandleConnections } from '@vue-flow/core'
import { Handle, useNodeConnections } from '@vue-flow/core'
import type { ProcessNodeData } from './types'

const props = defineProps<NodeProps<ProcessNodeData>>()

const sourceConnections = useHandleConnections({
type: 'target',
const sourceConnections = useNodeConnections({
handleType: 'target',
})

const targetConnections = useHandleConnections({
type: 'source',
const targetConnections = useNodeConnections({
handleType: 'source',
})

const isSender = toRef(() => sourceConnections.value.length <= 0)
Expand Down
15 changes: 7 additions & 8 deletions examples/vite/src/Math/ResultNode.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
<script setup lang="ts">
import type { GraphNode } from '@vue-flow/core'
import { Handle, Position, useHandleConnections, useNodesData, useVueFlow } from '@vue-flow/core'
import { Handle, Position, useNodeConnections, useNodesData } from '@vue-flow/core'
import type { OperatorNodeData, ValueNodeData } from './types'
import { mathFunctions } from './utils'

defineProps<{ id: string }>()

const { getConnectedEdges } = useVueFlow()

// Get the source connections of the result node. In this example it's only one operator node.
const sourceConnections = useHandleConnections({
const sourceConnections = useNodeConnections({
// type target means all connections where *this* node is the target
// that means we go backwards in the graph to find the source of the connection(s)
type: 'target',
handleType: 'target',
})

// Get the source connections of the operator node
const operatorSourceConnections = computed(() =>
getConnectedEdges(sourceConnections.value[0].source).filter((e) => e.source !== sourceConnections.value[0].source),
)
const operatorSourceConnections = useNodeConnections({
handleType: 'target',
nodeId: () => sourceConnections.value[0]?.source,
})

const operatorData = useNodesData<GraphNode<OperatorNodeData>>(() =>
sourceConnections.value.map((connection) => connection.source),
Expand Down
10 changes: 10 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# @vue-flow/core

## 1.42.0

### Minor Changes

- [#1729](https://github.com/bcakmakoglu/vue-flow/pull/1729) [`8a832f1`](https://github.com/bcakmakoglu/vue-flow/commit/8a832f1bc2eb045f95d9cc0e66bba7be559caad5) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Use connection lookup to check what elements should be selected by a user selection box.

- [#1729](https://github.com/bcakmakoglu/vue-flow/pull/1729) [`d4a6910`](https://github.com/bcakmakoglu/vue-flow/commit/d4a6910b90feb2169da32ded7738645853684338) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Add `useNodeConnections` composable

- [#1742](https://github.com/bcakmakoglu/vue-flow/pull/1742) [`b1e2f57`](https://github.com/bcakmakoglu/vue-flow/commit/b1e2f57bf77ccb33e6b2d20e4be69e8c0bd29327) Thanks [@bcakmakoglu](https://github.com/bcakmakoglu)! - Inherit attributes on main edge path element in BaseEdge component.

## 1.41.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vue-flow/core",
"version": "1.41.7",
"version": "1.42.0",
"private": false,
"license": "MIT",
"author": "Burak Cakmakoglu<78412429+bcakmakoglu@users.noreply.github.com>",
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/components/Edges/BaseEdge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ref, useAttrs } from 'vue'
import type { BaseEdgeProps } from '../../types'
import EdgeText from './EdgeText.vue'

const { interactionWidth = 20, labelShowBg = true, ...props } = defineProps<BaseEdgeProps>()
withDefaults(defineProps<BaseEdgeProps>(), { interactionWidth: 20 })

const pathEl = ref<SVGPathElement | null>(null)

Expand All @@ -30,12 +30,11 @@ export default {

<template>
<path
v-bind="attrs"
:id="id"
ref="pathEl"
:d="path"
:style="props.style"
class="vue-flow__edge-path"
:class="attrs.class"
:marker-end="markerEnd"
:marker-start="markerStart"
/>
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/composables/useHandleConnections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface UseHandleConnectionsParams {
/**
* Composable that returns existing connections of a `<Handle />`.
*
* @deprecated use `useNodeConnections` instead
* @public
* @param params
* @param params.type - handle type `source` or `target`
Expand Down
82 changes: 82 additions & 0 deletions packages/core/src/composables/useNodeConnections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { MaybeRefOrGetter } from 'vue'
import { computed, ref, toValue, watch } from 'vue'
import type { HandleType, NodeConnection } from '../types'
import { areConnectionMapsEqual, handleConnectionChange } from '../utils'
import { useNodeId } from './useNodeId'
import { useVueFlow } from './useVueFlow'

export interface UseNodeConnectionsParams {
handleType?: MaybeRefOrGetter<HandleType>
handleId?: MaybeRefOrGetter<string | null>
nodeId?: MaybeRefOrGetter<string | null>
onConnect?: (connections: NodeConnection[]) => void
onDisconnect?: (connections: NodeConnection[]) => void
}

/**
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
*
* @public
* @param params
* @param params.handleType - handle type `source` or `target`
* @param params.nodeId - node id - if not provided, the node id from the `useNodeId` (meaning, the context-based injection) is used
* @param params.handleId - the handle id (this is required if the node has multiple handles of the same type)
* @param params.onConnect - gets called when a connection is created
* @param params.onDisconnect - gets called when a connection is removed
*
* @returns An array of connections
*/
export function useNodeConnections(params: UseNodeConnectionsParams = {}) {
const { handleType, handleId, nodeId, onConnect, onDisconnect } = params

const { connectionLookup } = useVueFlow()

const _nodeId = useNodeId()

const prevConnections = ref<Map<string, NodeConnection> | null>(null)

const connections = ref<Map<string, NodeConnection>>()

const lookupKey = computed(() => {
const currNodeId = toValue(nodeId) ?? _nodeId
const currentHandleType = toValue(handleType)
const currHandleId = toValue(handleId)

return `${currNodeId}${
currentHandleType ? (currHandleId ? `-${currentHandleType}-${currHandleId}` : `-${currentHandleType}`) : ''
}`
})

watch(
() => connectionLookup.value.get(lookupKey.value),
(nextConnections) => {
if (areConnectionMapsEqual(connections.value, nextConnections)) {
return
}

connections.value = nextConnections
},
{ immediate: true },
)

watch(
[connections, () => typeof onConnect !== 'undefined', () => typeof onDisconnect !== 'undefined'],
([currentConnections = new Map<string, NodeConnection>()]) => {
if (prevConnections.value && prevConnections.value !== currentConnections) {
handleConnectionChange(prevConnections.value, currentConnections, onDisconnect)
handleConnectionChange(currentConnections, prevConnections.value, onConnect)
}

prevConnections.value = currentConnections
},
{ immediate: true },
)

return computed(() => {
if (!connections.value) {
return []
}

return Array.from(connections.value.values())
})
}
Loading
Loading