refactor(nodes): use HandleConnectable type for nodes connectable prop
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { isString } from '@vueuse/core'
|
import { isFunction, isString } from '@vueuse/core'
|
||||||
import { useHandle, useNode, useVueFlow } from '../../composables'
|
import { useHandle, useNode, useVueFlow } from '../../composables'
|
||||||
import type { Position } from '../../types'
|
import type { Position } from '../../types'
|
||||||
import { ConnectionMode } from '../../types'
|
import { ConnectionMode } from '../../types'
|
||||||
@@ -8,7 +8,7 @@ import { getDimensions } from '../../utils'
|
|||||||
|
|
||||||
const { type = 'source', position = 'top' as Position, connectable = true, id, isValidConnection } = defineProps<HandleProps>()
|
const { type = 'source', position = 'top' as Position, connectable = true, id, isValidConnection } = defineProps<HandleProps>()
|
||||||
|
|
||||||
const { connectionStartHandle, connectionMode, vueFlowRef } = $(useVueFlow())
|
const { connectionStartHandle, connectionMode, vueFlowRef, nodesConnectable } = $(useVueFlow())
|
||||||
|
|
||||||
const { id: nodeId, node, nodeEl, connectedEdges } = useNode()
|
const { id: nodeId, node, nodeEl, connectedEdges } = useNode()
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@ const handleId = $computed(() => id ?? (connectionMode === ConnectionMode.Strict
|
|||||||
const isConnectable = computed(() => {
|
const isConnectable = computed(() => {
|
||||||
if (isString(connectable) && connectable === 'single') {
|
if (isString(connectable) && connectable === 'single') {
|
||||||
return !connectedEdges.value.some((edge) => edge[type] === nodeId && edge[`${type}Handle`] === handleId)
|
return !connectedEdges.value.some((edge) => edge[type] === nodeId && edge[`${type}Handle`] === handleId)
|
||||||
|
} else if (isFunction(connectable)) {
|
||||||
|
return connectable(node, connectedEdges.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return connectable
|
return connectable
|
||||||
@@ -34,25 +36,6 @@ const onClickHandler = (event: MouseEvent) => {
|
|||||||
onClick(event, handleId ?? null, nodeId, type, isValidConnection)
|
onClick(event, handleId ?? null, nodeId, type, isValidConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getClasses = computed(() => {
|
|
||||||
return [
|
|
||||||
'vue-flow__handle',
|
|
||||||
`vue-flow__handle-${position}`,
|
|
||||||
`vue-flow__handle-${handleId}`,
|
|
||||||
'nodrag',
|
|
||||||
{
|
|
||||||
source: type !== 'target',
|
|
||||||
target: type === 'target',
|
|
||||||
connectable: isConnectable,
|
|
||||||
connecting:
|
|
||||||
connectionStartHandle &&
|
|
||||||
connectionStartHandle.nodeId === nodeId &&
|
|
||||||
connectionStartHandle.handleId === handleId &&
|
|
||||||
connectionStartHandle.type === type,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const existingBounds = node.handleBounds[type]?.find((b) => b.id === handleId)
|
const existingBounds = node.handleBounds[type]?.find((b) => b.id === handleId)
|
||||||
if (!vueFlowRef || existingBounds) return
|
if (!vueFlowRef || existingBounds) return
|
||||||
@@ -92,7 +75,21 @@ export default {
|
|||||||
:data-handleid="handleId"
|
:data-handleid="handleId"
|
||||||
:data-nodeid="nodeId"
|
:data-nodeid="nodeId"
|
||||||
:data-handlepos="position"
|
:data-handlepos="position"
|
||||||
:class="getClasses"
|
class="vue-flow__handle nodrag"
|
||||||
|
:class="[
|
||||||
|
`vue-flow__handle-${position}`,
|
||||||
|
`vue-flow__handle-${handleId}`,
|
||||||
|
{
|
||||||
|
source: type !== 'target',
|
||||||
|
target: type === 'target',
|
||||||
|
connectable: isConnectable,
|
||||||
|
connecting:
|
||||||
|
connectionStartHandle &&
|
||||||
|
connectionStartHandle.nodeId === nodeId &&
|
||||||
|
connectionStartHandle.handleId === handleId &&
|
||||||
|
connectionStartHandle.type === type,
|
||||||
|
},
|
||||||
|
]"
|
||||||
@mousedown="onMouseDownHandler"
|
@mousedown="onMouseDownHandler"
|
||||||
@click="onClickHandler"
|
@click="onClickHandler"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
import { useDrag, useNodeHooks, useVueFlow } from '../../composables'
|
import { useDrag, useNodeHooks, useVueFlow } from '../../composables'
|
||||||
import type { GraphNode, NodeComponent, SnapGrid, XYZPosition } from '../../types'
|
import type { GraphNode, HandleConnectable, NodeComponent, SnapGrid, XYZPosition } from '../../types'
|
||||||
import { NodeId, NodeRef } from '../../context'
|
import { NodeId, NodeRef } from '../../context'
|
||||||
import { getConnectedEdges, getXYZPos, handleNodeClick } from '../../utils'
|
import { getConnectedEdges, getXYZPos, handleNodeClick } from '../../utils'
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ const { id, type, name, draggable, selectable, connectable, snapGrid, ...props }
|
|||||||
id: string
|
id: string
|
||||||
draggable: boolean
|
draggable: boolean
|
||||||
selectable: boolean
|
selectable: boolean
|
||||||
connectable: boolean
|
connectable: HandleConnectable
|
||||||
snapGrid?: SnapGrid
|
snapGrid?: SnapGrid
|
||||||
type: NodeComponent | Function | Object | false
|
type: NodeComponent | Function | Object | false
|
||||||
name: string
|
name: string
|
||||||
@@ -39,6 +39,8 @@ const node = $(useVModel(props, 'node'))
|
|||||||
|
|
||||||
const parentNode = $computed(() => (node.parentNode ? getNode(node.parentNode) : undefined))
|
const parentNode = $computed(() => (node.parentNode ? getNode(node.parentNode) : undefined))
|
||||||
|
|
||||||
|
const connectedEdges = $computed(() => getConnectedEdges([node], edges))
|
||||||
|
|
||||||
const nodeElement = ref()
|
const nodeElement = ref()
|
||||||
|
|
||||||
provide(NodeRef, nodeElement)
|
provide(NodeRef, nodeElement)
|
||||||
@@ -137,19 +139,19 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
const onMouseEnter = (event: MouseEvent) => {
|
const onMouseEnter = (event: MouseEvent) => {
|
||||||
if (!dragging?.value) {
|
if (!dragging?.value) {
|
||||||
emit.mouseEnter({ event, node, connectedEdges: getConnectedEdges([node], edges) })
|
emit.mouseEnter({ event, node, connectedEdges })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMouseMove = (event: MouseEvent) => {
|
const onMouseMove = (event: MouseEvent) => {
|
||||||
if (!dragging?.value) {
|
if (!dragging?.value) {
|
||||||
emit.mouseMove({ event, node, connectedEdges: getConnectedEdges([node], edges) })
|
emit.mouseMove({ event, node, connectedEdges })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onMouseLeave = (event: MouseEvent) => {
|
const onMouseLeave = (event: MouseEvent) => {
|
||||||
if (!dragging?.value) {
|
if (!dragging?.value) {
|
||||||
emit.mouseLeave({ event, node, connectedEdges: getConnectedEdges([node], edges) })
|
emit.mouseLeave({ event, node, connectedEdges })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ export default function useNode<Data = ElementData, CustomEvents extends Record<
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
node,
|
|
||||||
nodeEl,
|
nodeEl,
|
||||||
parentNode: node.parentNode ? findNode(node.parentNode) : undefined,
|
node,
|
||||||
|
parentNode: computed(() => (node.parentNode ? findNode(node.parentNode) : undefined)),
|
||||||
connectedEdges: computed(() => getConnectedEdges([node], getEdges.value)),
|
connectedEdges: computed(() => getConnectedEdges([node], getEdges.value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ export type ValidConnectionFunc = (
|
|||||||
elements: { edges: GraphEdge[]; sourceNode: GraphNode; targetNode: GraphNode },
|
elements: { edges: GraphEdge[]; sourceNode: GraphNode; targetNode: GraphNode },
|
||||||
) => boolean
|
) => boolean
|
||||||
|
|
||||||
|
/** set to true to allow unlimited connections, single for only one connection or use a cb function to determine connect-ability */
|
||||||
|
export type HandleConnectable = boolean | 'single' | ((node: GraphNode, connectedEdges: GraphEdge[]) => boolean)
|
||||||
|
|
||||||
export interface HandleProps {
|
export interface HandleProps {
|
||||||
/** Unique id of handle element */
|
/** Unique id of handle element */
|
||||||
id?: string
|
id?: string
|
||||||
@@ -32,5 +35,5 @@ export interface HandleProps {
|
|||||||
/** A valid connection func {@link ValidConnectionFunc} */
|
/** A valid connection func {@link ValidConnectionFunc} */
|
||||||
isValidConnection?: ValidConnectionFunc
|
isValidConnection?: ValidConnectionFunc
|
||||||
/** Enable/disable connecting to handle */
|
/** Enable/disable connecting to handle */
|
||||||
connectable?: boolean | 'single'
|
connectable?: HandleConnectable
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Component, VNode } from 'vue'
|
import type { Component, VNode } from 'vue'
|
||||||
import type { ClassFunc, Dimensions, ElementData, Position, SnapGrid, StyleFunc, Styles, XYPosition, XYZPosition } from './flow'
|
import type { ClassFunc, Dimensions, ElementData, Position, SnapGrid, StyleFunc, Styles, XYPosition, XYZPosition } from './flow'
|
||||||
import type { DefaultNodeTypes, NodeComponent } from './components'
|
import type { DefaultNodeTypes, NodeComponent } from './components'
|
||||||
import type { HandleElement, ValidConnectionFunc } from './handle'
|
import type { HandleConnectable, HandleElement, ValidConnectionFunc } from './handle'
|
||||||
import type { CustomEvent, NodeEventsHandler, NodeEventsOn } from './hooks'
|
import type { CustomEvent, NodeEventsHandler, NodeEventsOn } from './hooks'
|
||||||
|
|
||||||
/** Defined as [[x-from, y-from], [x-to, y-to]] **/
|
/** Defined as [[x-from, y-from], [x-to, y-to]] **/
|
||||||
@@ -31,7 +31,7 @@ export interface Node<Data = ElementData, CustomEvents extends Record<string, Cu
|
|||||||
sourcePosition?: Position
|
sourcePosition?: Position
|
||||||
draggable?: boolean
|
draggable?: boolean
|
||||||
selectable?: boolean
|
selectable?: boolean
|
||||||
connectable?: boolean
|
connectable?: HandleConnectable
|
||||||
dragHandle?: string
|
dragHandle?: string
|
||||||
/** move on grid */
|
/** move on grid */
|
||||||
snapGrid?: SnapGrid
|
snapGrid?: SnapGrid
|
||||||
@@ -93,8 +93,8 @@ export interface NodeProps<Data = ElementData, CustomEvents = {}> {
|
|||||||
type: keyof DefaultNodeTypes | string
|
type: keyof DefaultNodeTypes | string
|
||||||
/** is node selected */
|
/** is node selected */
|
||||||
selected: boolean
|
selected: boolean
|
||||||
/** can node be connected */
|
/** can node handles be connected */
|
||||||
connectable: boolean
|
connectable: HandleConnectable
|
||||||
/** node x, y (relative) position on graph */
|
/** node x, y (relative) position on graph */
|
||||||
position: XYPosition
|
position: XYPosition
|
||||||
/** dom element dimensions (width, height) */
|
/** dom element dimensions (width, height) */
|
||||||
|
|||||||
Reference in New Issue
Block a user