Skip to content

Commit e047be6

Browse files
committed
feat(vue-flow): add autoConnect option
# What's changed? * auto-connect allows to easily enable the default add edge change handler (shown in the examples) * allow auto-connect to be a function that returns false when connection is cancelled or partial edge when it should be created
1 parent 5a563e4 commit e047be6

File tree

6 files changed

+62
-7
lines changed

6 files changed

+62
-7
lines changed

packages/vue-flow/src/container/VueFlow/VueFlow.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const props = withDefaults(defineProps<FlowProps>(), {
3636
fitViewOnInit: undefined,
3737
connectOnClick: undefined,
3838
connectionLineStyle: undefined,
39+
autoConnect: undefined,
3940
})
4041
4142
const emit = defineEmits<{

packages/vue-flow/src/container/VueFlow/watch.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Ref, ToRefs } from 'vue'
22
import type { WatchPausableReturn } from '@vueuse/core'
3-
import type { FlowProps, GraphEdge, GraphNode, VueFlowStore } from '~/types'
3+
import { isFunction } from '@vueuse/core'
4+
import type { Connection, FlowProps, GraphEdge, GraphNode, VueFlowStore } from '~/types'
45

56
const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined'
67
export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>>, props: FlowProps, store: VueFlowStore) => {
@@ -171,8 +172,45 @@ export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>
171172
})
172173
}
173174

175+
const watchAutoConnect = () => {
176+
scope.run(() => {
177+
watch(
178+
() => props.autoConnect,
179+
() => {
180+
if (isDef(props.autoConnect)) {
181+
store.autoConnect.value = props.autoConnect
182+
}
183+
},
184+
{ immediate: isDef(props.autoConnect) },
185+
)
186+
187+
watch(
188+
store.autoConnect,
189+
() => {
190+
const autoConnector = async (params: Connection) => {
191+
let connect: boolean | Connection = true
192+
if (isFunction(props.autoConnect)) {
193+
connect = await props.autoConnect(params)
194+
}
195+
196+
if (connect) {
197+
store.addEdges([params])
198+
}
199+
}
200+
201+
if (store.autoConnect) {
202+
store.onConnect(autoConnector)
203+
} else {
204+
store.hooks.value.connect.off(autoConnector)
205+
}
206+
},
207+
{ immediate: true },
208+
)
209+
})
210+
}
211+
174212
const watchRest = () => {
175-
const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault']
213+
const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault', 'autoConnect']
176214
Object.keys(props).forEach((prop) => {
177215
if (!skip.includes(prop)) {
178216
const model = props[prop as keyof typeof props]
@@ -193,9 +231,16 @@ export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>
193231
})
194232
}
195233

196-
;[watchModelValue, watchNodesValue, watchEdgesValue, watchMinZoom, watchMaxZoom, watchApplyDefault, watchRest].forEach(
197-
(watch) => watch(),
198-
)
234+
;[
235+
watchModelValue,
236+
watchNodesValue,
237+
watchEdgesValue,
238+
watchMinZoom,
239+
watchMaxZoom,
240+
watchApplyDefault,
241+
watchAutoConnect,
242+
watchRest,
243+
].forEach((watch) => watch())
199244
})
200245

201246
return () => scope.stop()

packages/vue-flow/src/store/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const defaultState = (): State => ({
101101
hooks: createHooks(),
102102

103103
applyDefault: true,
104+
autoConnect: false,
104105

105106
fitViewOnInit: false,
106107
noDragClassName: 'nodrag',

packages/vue-flow/src/types/connection.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { CSSProperties } from 'vue'
22
import type { Position } from './flow'
33
import type { GraphNode } from './node'
44
import type { HandleElement, HandleType } from './handle'
5+
import type { Edge } from './edge'
56

67
/** Connection line types (same as default edge types */
78
export enum ConnectionLineType {
@@ -23,6 +24,10 @@ export interface Connection {
2324
targetHandle: string | null
2425
}
2526

27+
export type Connector = (
28+
params: Connection,
29+
) => Promise<(Connection & Partial<Edge>) | false> | ((Connection & Partial<Edge>) | false)
30+
2631
/** The source nodes params when connection is initiated */
2732
export interface OnConnectStartParams {
2833
/** Source node id */

packages/vue-flow/src/types/flow.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { CSSProperties } from 'vue'
22
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
33
import type { CoordinateExtent, GraphNode, Node } from './node'
4-
import type { ConnectionLineType, ConnectionMode } from './connection'
4+
import type { ConnectionLineType, ConnectionMode, Connector } from './connection'
55
import type { KeyCode, PanOnScrollMode } from './zoom'
66
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
77

@@ -122,6 +122,8 @@ export interface FlowProps {
122122
connectOnClick?: boolean
123123
/** apply default change handlers for position, dimensions, adding/removing nodes. set this to false if you want to apply the changes manually */
124124
applyDefault?: boolean
125+
/** automatically create an edge when connection is triggered */
126+
autoConnect?: boolean | Connector
125127
noDragClassName?: string
126128
noWheelClassName?: string
127129
noPanClassName?: string

packages/vue-flow/src/types/store.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { CSSProperties, ComputedRef, ToRefs } from 'vue'
22
import type { Dimensions, ElementData, Elements, FlowElements, FlowExportObject, FlowOptions, SnapGrid, XYPosition } from './flow'
33
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
4-
import type { Connection, ConnectionLineType, ConnectionMode } from './connection'
4+
import type { Connection, ConnectionLineType, ConnectionMode, Connector } from './connection'
55
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
66
import type { CoordinateExtent, GraphNode, Node } from './node'
77
import type { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode, Viewport, ViewportFunctions } from './zoom'
@@ -88,6 +88,7 @@ export interface State extends Omit<FlowOptions, 'id' | 'modelValue'> {
8888

8989
initialized: boolean
9090
applyDefault: boolean
91+
autoConnect: boolean | Connector
9192

9293
fitViewOnInit?: boolean
9394

0 commit comments

Comments
 (0)