From 05bc748100db824a23803a8607a78e1387c0d565 Mon Sep 17 00:00:00 2001 From: braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Tue, 7 Mar 2023 22:05:37 +0100 Subject: [PATCH] feat(core): add `isValidConnection` prop Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com> --- .../core/src/components/Edges/EdgeWrapper.ts | 3 ++- packages/core/src/composables/useHandle.ts | 15 ++++++------ .../core/src/container/VueFlow/VueFlow.vue | 1 + packages/core/src/store/actions.ts | 24 +++++++++++++++++-- packages/core/src/types/flow.ts | 2 ++ packages/core/src/types/store.ts | 3 ++- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/packages/core/src/components/Edges/EdgeWrapper.ts b/packages/core/src/components/Edges/EdgeWrapper.ts index a8270741..12af97d1 100644 --- a/packages/core/src/components/Edges/EdgeWrapper.ts +++ b/packages/core/src/components/Edges/EdgeWrapper.ts @@ -29,6 +29,7 @@ const EdgeWrapper = defineComponent({ removeSelectedEdges, findEdge, findNode, + isValidConnection, } = useVueFlow() const hooks = useEdgeHooks(props.edge, emits) @@ -60,7 +61,7 @@ const EdgeWrapper = defineComponent({ nodeId, handleId, type, - isValidConnection: undefined, + isValidConnection: isValidConnection.value, edgeUpdaterType, onEdgeUpdate, onEdgeUpdateEnd, diff --git a/packages/core/src/composables/useHandle.ts b/packages/core/src/composables/useHandle.ts index c6d1b1e1..7d6567fe 100644 --- a/packages/core/src/composables/useHandle.ts +++ b/packages/core/src/composables/useHandle.ts @@ -5,7 +5,7 @@ interface UseHandleProps { handleId: MaybeRef nodeId: MaybeRef type: MaybeRef - isValidConnection?: ValidConnectionFunc + isValidConnection?: ValidConnectionFunc | null edgeUpdaterType?: MaybeRef onEdgeUpdate?: (event: MouseTouchEvent, connection: Connection) => void onEdgeUpdateEnd?: (event: MouseTouchEvent) => void @@ -44,6 +44,7 @@ export default function useHandle({ emits, viewport, edges, + isValidConnection: isValidConnectionProp, } = useVueFlow() let connection: Connection | null = null @@ -59,10 +60,10 @@ export default function useHandle({ const node = findNode(unref(nodeId)) - let validConnectFunc = isValidConnection || alwaysValid + let isValidConnectionHandler = isValidConnection || isValidConnectionProp.value || alwaysValid if (!isValidConnection) { - if (node) validConnectFunc = (!isTarget ? node.isValidTargetPos : node.isValidSourcePos) || alwaysValid + if (node) isValidConnectionHandler = (!isTarget ? node.isValidTargetPos : node.isValidSourcePos) || alwaysValid } let prevClosestHandle: ConnectionHandle | null @@ -136,7 +137,7 @@ export default function useHandle({ nodeId, handleId, isTarget ? 'target' : 'source', - validConnectFunc, + isValidConnectionHandler, doc, edges.value, findNode, @@ -218,12 +219,12 @@ export default function useHandle({ if (!connectionClickStartHandle.value) { startConnection({ nodeId: unref(nodeId), type: unref(type), handleId: unref(handleId) }, undefined, event, true) } else { - let validConnectFunc = isValidConnection ?? alwaysValid + let isValidConnectionHandler = isValidConnection || isValidConnectionProp.value || alwaysValid const node = findNode(unref(nodeId)) if (!isValidConnection) { - if (node) validConnectFunc = (!isTarget ? node.isValidTargetPos : node.isValidSourcePos) || alwaysValid + if (node) isValidConnectionHandler = (!isTarget ? node.isValidTargetPos : node.isValidSourcePos) || alwaysValid } if (node && (typeof node.connectable === 'undefined' ? nodesConnectable : node.connectable) === false) return @@ -241,7 +242,7 @@ export default function useHandle({ connectionClickStartHandle.value.nodeId, connectionClickStartHandle.value.handleId || null, connectionClickStartHandle.value.type, - validConnectFunc, + isValidConnectionHandler, doc, edges.value, findNode, diff --git a/packages/core/src/container/VueFlow/VueFlow.vue b/packages/core/src/container/VueFlow/VueFlow.vue index c34dbc9d..c370168e 100644 --- a/packages/core/src/container/VueFlow/VueFlow.vue +++ b/packages/core/src/container/VueFlow/VueFlow.vue @@ -45,6 +45,7 @@ const props = withDefaults(defineProps(), { nodesFocusable: undefined, autoPanOnConnect: undefined, autoPanOnNodeDrag: undefined, + isValidConnection: undefined, }) const emit = defineEmits<{ diff --git a/packages/core/src/store/actions.ts b/packages/core/src/store/actions.ts index 12ba98b4..b4a28c98 100644 --- a/packages/core/src/store/actions.ts +++ b/packages/core/src/store/actions.ts @@ -298,7 +298,17 @@ export function useActions(state: State, getters: ComputedGetters): Actions { if (!state.initialized && !nextEdges.length) return - state.edges = nextEdges.reduce((res, edge) => { + const validEdges = state.isValidConnection + ? nextEdges.filter((edge) => + state.isValidConnection!(edge, { + edges: state.edges, + sourceNode: findNode(edge.source)!, + targetNode: findNode(edge.target)!, + }), + ) + : nextEdges + + state.edges = validEdges.reduce((res, edge) => { const sourceNode = findNode(edge.source)! const targetNode = findNode(edge.target)! @@ -343,7 +353,17 @@ export function useActions(state: State, getters: ComputedGetters): Actions { const addEdges: Actions['addEdges'] = (params) => { const nextEdges = params instanceof Function ? params(state.edges) : params - const changes = nextEdges.reduce((acc, param) => { + const validEdges = state.isValidConnection + ? nextEdges.filter((edge) => + state.isValidConnection!(edge, { + edges: state.edges, + sourceNode: findNode(edge.source)!, + targetNode: findNode(edge.target)!, + }), + ) + : nextEdges + + const changes = validEdges.reduce((acc, param) => { const edge = addEdgeToStore( { ...param, diff --git a/packages/core/src/types/flow.ts b/packages/core/src/types/flow.ts index d1183eb2..6547cf6f 100644 --- a/packages/core/src/types/flow.ts +++ b/packages/core/src/types/flow.ts @@ -6,6 +6,7 @@ import type { Connection, ConnectionLineOptions, ConnectionLineType, ConnectionM import type { PanOnScrollMode, ViewportTransform } from './zoom' import type { EdgeTypesObject, NodeTypesObject } from './components' import type { CustomEvent } from './hooks' +import type { ValidConnectionFunc } from '~/types/handle' export type ElementData = any @@ -119,6 +120,7 @@ export interface FlowProps { connectionLineStyle?: CSSProperties | null connectionLineOptions?: ConnectionLineOptions connectionRadius?: number + isValidConnection?: ValidConnectionFunc | null deleteKeyCode?: KeyFilter | null selectionKeyCode?: KeyFilter | null multiSelectionKeyCode?: KeyFilter | null diff --git a/packages/core/src/types/store.ts b/packages/core/src/types/store.ts index 4577870b..ca50c228 100644 --- a/packages/core/src/types/store.ts +++ b/packages/core/src/types/store.ts @@ -27,7 +27,7 @@ import type { CoordinateExtent, GraphNode, Node } from './node' import type { D3Selection, D3Zoom, D3ZoomHandler, PanOnScrollMode, ViewportFunctions, ViewportTransform } from './zoom' import type { CustomEvent, FlowHooks, FlowHooksEmit, FlowHooksOn } from './hooks' import type { EdgeChange, NodeChange, NodeDragItem } from './changes' -import type { StartHandle, ValidHandleResult } from './handle' +import type { StartHandle, ValidConnectionFunc, ValidHandleResult } from './handle' export interface UpdateNodeDimensionsParams { id: string @@ -89,6 +89,7 @@ export interface State extends Omit { connectionPosition: XYPosition connectionRadius: number connectionStatus: ConnectionStatus | null + isValidConnection: ValidConnectionFunc | null connectOnClick: boolean edgeUpdaterRadius: number