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
This commit is contained in:
@@ -36,6 +36,7 @@ const props = withDefaults(defineProps<FlowProps>(), {
|
|||||||
fitViewOnInit: undefined,
|
fitViewOnInit: undefined,
|
||||||
connectOnClick: undefined,
|
connectOnClick: undefined,
|
||||||
connectionLineStyle: undefined,
|
connectionLineStyle: undefined,
|
||||||
|
autoConnect: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Ref, ToRefs } from 'vue'
|
import type { Ref, ToRefs } from 'vue'
|
||||||
import type { WatchPausableReturn } from '@vueuse/core'
|
import type { WatchPausableReturn } from '@vueuse/core'
|
||||||
import type { FlowProps, GraphEdge, GraphNode, VueFlowStore } from '~/types'
|
import { isFunction } from '@vueuse/core'
|
||||||
|
import type { Connection, FlowProps, GraphEdge, GraphNode, VueFlowStore } from '~/types'
|
||||||
|
|
||||||
const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined'
|
const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined'
|
||||||
export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>>, props: FlowProps, store: VueFlowStore) => {
|
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'>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const watchAutoConnect = () => {
|
||||||
|
scope.run(() => {
|
||||||
|
watch(
|
||||||
|
() => props.autoConnect,
|
||||||
|
() => {
|
||||||
|
if (isDef(props.autoConnect)) {
|
||||||
|
store.autoConnect.value = props.autoConnect
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: isDef(props.autoConnect) },
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
store.autoConnect,
|
||||||
|
() => {
|
||||||
|
const autoConnector = async (params: Connection) => {
|
||||||
|
let connect: boolean | Connection = true
|
||||||
|
if (isFunction(props.autoConnect)) {
|
||||||
|
connect = await props.autoConnect(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect) {
|
||||||
|
store.addEdges([params])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store.autoConnect) {
|
||||||
|
store.onConnect(autoConnector)
|
||||||
|
} else {
|
||||||
|
store.hooks.value.connect.off(autoConnector)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const watchRest = () => {
|
const watchRest = () => {
|
||||||
const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault']
|
const skip = ['id', 'modelValue', 'edges', 'nodes', 'maxZoom', 'minZoom', 'applyDefault', 'autoConnect']
|
||||||
Object.keys(props).forEach((prop) => {
|
Object.keys(props).forEach((prop) => {
|
||||||
if (!skip.includes(prop)) {
|
if (!skip.includes(prop)) {
|
||||||
const model = props[prop as keyof typeof props]
|
const model = props[prop as keyof typeof props]
|
||||||
@@ -193,9 +231,16 @@ export default (models: ToRefs<Pick<FlowProps, 'nodes' | 'edges' | 'modelValue'>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
;[watchModelValue, watchNodesValue, watchEdgesValue, watchMinZoom, watchMaxZoom, watchApplyDefault, watchRest].forEach(
|
;[
|
||||||
(watch) => watch(),
|
watchModelValue,
|
||||||
)
|
watchNodesValue,
|
||||||
|
watchEdgesValue,
|
||||||
|
watchMinZoom,
|
||||||
|
watchMaxZoom,
|
||||||
|
watchApplyDefault,
|
||||||
|
watchAutoConnect,
|
||||||
|
watchRest,
|
||||||
|
].forEach((watch) => watch())
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => scope.stop()
|
return () => scope.stop()
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ const defaultState = (): State => ({
|
|||||||
hooks: createHooks(),
|
hooks: createHooks(),
|
||||||
|
|
||||||
applyDefault: true,
|
applyDefault: true,
|
||||||
|
autoConnect: false,
|
||||||
|
|
||||||
fitViewOnInit: false,
|
fitViewOnInit: false,
|
||||||
noDragClassName: 'nodrag',
|
noDragClassName: 'nodrag',
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { CSSProperties } from 'vue'
|
|||||||
import type { Position } from './flow'
|
import type { Position } from './flow'
|
||||||
import type { GraphNode } from './node'
|
import type { GraphNode } from './node'
|
||||||
import type { HandleElement, HandleType } from './handle'
|
import type { HandleElement, HandleType } from './handle'
|
||||||
|
import type { Edge } from './edge'
|
||||||
|
|
||||||
/** Connection line types (same as default edge types */
|
/** Connection line types (same as default edge types */
|
||||||
export enum ConnectionLineType {
|
export enum ConnectionLineType {
|
||||||
@@ -23,6 +24,10 @@ export interface Connection {
|
|||||||
targetHandle: string | null
|
targetHandle: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Connector = (
|
||||||
|
params: Connection,
|
||||||
|
) => Promise<(Connection & Partial<Edge>) | false> | ((Connection & Partial<Edge>) | false)
|
||||||
|
|
||||||
/** The source nodes params when connection is initiated */
|
/** The source nodes params when connection is initiated */
|
||||||
export interface OnConnectStartParams {
|
export interface OnConnectStartParams {
|
||||||
/** Source node id */
|
/** Source node id */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { CSSProperties } from 'vue'
|
import type { CSSProperties } from 'vue'
|
||||||
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
||||||
import type { CoordinateExtent, GraphNode, Node } from './node'
|
import type { CoordinateExtent, GraphNode, Node } from './node'
|
||||||
import type { ConnectionLineType, ConnectionMode } from './connection'
|
import type { ConnectionLineType, ConnectionMode, Connector } from './connection'
|
||||||
import type { KeyCode, PanOnScrollMode } from './zoom'
|
import type { KeyCode, PanOnScrollMode } from './zoom'
|
||||||
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
|
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
|
||||||
|
|
||||||
@@ -122,6 +122,8 @@ export interface FlowProps {
|
|||||||
connectOnClick?: boolean
|
connectOnClick?: boolean
|
||||||
/** apply default change handlers for position, dimensions, adding/removing nodes. set this to false if you want to apply the changes manually */
|
/** apply default change handlers for position, dimensions, adding/removing nodes. set this to false if you want to apply the changes manually */
|
||||||
applyDefault?: boolean
|
applyDefault?: boolean
|
||||||
|
/** automatically create an edge when connection is triggered */
|
||||||
|
autoConnect?: boolean | Connector
|
||||||
noDragClassName?: string
|
noDragClassName?: string
|
||||||
noWheelClassName?: string
|
noWheelClassName?: string
|
||||||
noPanClassName?: string
|
noPanClassName?: string
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { CSSProperties, ComputedRef, ToRefs } from 'vue'
|
import type { CSSProperties, ComputedRef, ToRefs } from 'vue'
|
||||||
import type { Dimensions, ElementData, Elements, FlowElements, FlowExportObject, FlowOptions, SnapGrid, XYPosition } from './flow'
|
import type { Dimensions, ElementData, Elements, FlowElements, FlowExportObject, FlowOptions, SnapGrid, XYPosition } from './flow'
|
||||||
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
|
import type { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from './components'
|
||||||
import type { Connection, ConnectionLineType, ConnectionMode } from './connection'
|
import type { Connection, ConnectionLineType, ConnectionMode, Connector } from './connection'
|
||||||
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
import type { DefaultEdgeOptions, Edge, GraphEdge } from './edge'
|
||||||
import type { CoordinateExtent, GraphNode, Node } from './node'
|
import type { CoordinateExtent, GraphNode, Node } from './node'
|
||||||
import type { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode, Viewport, ViewportFunctions } from './zoom'
|
import type { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode, Viewport, ViewportFunctions } from './zoom'
|
||||||
@@ -88,6 +88,7 @@ export interface State extends Omit<FlowOptions, 'id' | 'modelValue'> {
|
|||||||
|
|
||||||
initialized: boolean
|
initialized: boolean
|
||||||
applyDefault: boolean
|
applyDefault: boolean
|
||||||
|
autoConnect: boolean | Connector
|
||||||
|
|
||||||
fitViewOnInit?: boolean
|
fitViewOnInit?: boolean
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user