Files
vue-flow/src/composables/useElementsState.ts
T

125 lines
3.9 KiB
TypeScript

import useVueFlow from './useVueFlow'
import {
GraphEdge,
NodeChange,
EdgeChange,
UseEdgesStateOptions,
UseEdgesState,
Edge,
Connection,
GraphNode,
UseNodesStateOptions,
UseNodesState,
UseElementsStateOptions,
UseElementsState,
} from '~/types'
import { applyChanges, connectionExists, getEdgeId, isEdge, isGraphEdge, parseEdge } from '~/utils'
import { parseChildren } from '~/store'
const addEdge = (edgeParams: Edge | Connection, edges: Edge[]) => {
if (!edgeParams.source || !edgeParams.target) {
console.warn("Can't create edge. An edge needs a source and a target.")
return false
}
let edge
if (isEdge(edgeParams)) {
edge = { ...edgeParams }
} else {
edge = {
...edgeParams,
id: getEdgeId(edgeParams),
} as Edge
}
edge = parseEdge(edge)
if (connectionExists(edge, edges)) return false
return edge
}
const updateEdge = (edge: GraphEdge, newConnection: Connection, edges: GraphEdge[]) => {
if (!newConnection.source || !newConnection.target) {
console.warn("Can't create new edge. An edge needs a source and a target.")
return false
}
const foundEdge = edges.find((e) => isGraphEdge(e) && e.id === edge.id)
if (!foundEdge) {
console.warn(`The old edge with id=${edge.id} does not exist.`)
return false
}
edge.id = getEdgeId(newConnection)
edge.source = newConnection.source
edge.target = newConnection.target
edge.sourceHandle = newConnection.sourceHandle
edge.targetHandle = newConnection.targetHandle
return edge
}
export const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
export const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
export const useEdgesState = ({ edges, options }: UseEdgesStateOptions = {}): UseEdgesState => {
const { store } = useVueFlow(options)
if (edges && edges.length) store.setEdges(edges)
return {
edges: store.edges,
applyEdgeChanges: (changes) => applyEdgeChanges(changes, store.edges),
setEdges: store.setEdges,
addEdges: (params) => {
params.forEach((param) => {
const edge = addEdge(param, store.edges)
if (edge) {
const sourceNode = store.getNode(edge.source)!
const targetNode = store.getNode(edge.target)!
if (!sourceNode || typeof sourceNode === 'undefined')
console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`)
if (!targetNode || typeof targetNode === 'undefined')
console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`)
store.edges.push({
...edge,
sourceNode,
targetNode,
})
}
})
return store.edges
},
updateEdge: (oldEdge, newConnection) => updateEdge(oldEdge, newConnection, store.edges),
onEdgesChange: store.hooksOn.onEdgesChange,
}
}
export const useNodesState = ({ nodes, options }: UseNodesStateOptions = {}): UseNodesState => {
const { store } = useVueFlow(options)
if (nodes && nodes.length) store.setNodes(nodes)
return {
nodes: store.nodes,
applyNodeChanges: (changes) => applyNodeChanges(changes, store.nodes),
setNodes: store.setNodes,
addNodes: (nodes, extent) => {
const parsed = nodes.flatMap((node) => {
const children: GraphNode[] = []
parseChildren(node, undefined, children, extent ?? store.nodeExtent, store.getNode)
return children
})
store.nodes.push(...parsed)
return store.nodes
},
onNodesChange: store.hooksOn.onNodesChange,
}
}
export const useElementsState = ({ edges, nodes, options }: UseElementsStateOptions = {}): UseElementsState => {
const nodesState = useNodesState({ nodes, options })
const edgesState = useEdgesState({ edges, options })
return {
...nodesState,
...edgesState,
}
}