refactor(flow): export useNodesState and useEdgesState separately from useVueFlow
* bind vueFlow instance to currentInstance when useVueFlow is called multiple times in a single setup call Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { mount } from '@cypress/vue'
|
|||||||
import VueFlow from '../../../src/container/VueFlow/VueFlow.vue'
|
import VueFlow from '../../../src/container/VueFlow/VueFlow.vue'
|
||||||
import { Elements } from '~/types'
|
import { Elements } from '~/types'
|
||||||
import { isEdge, isNode } from '~/utils'
|
import { isEdge, isNode } from '~/utils'
|
||||||
|
import '~/theme-default.css'
|
||||||
|
|
||||||
describe('Render VueFlow', () => {
|
describe('Render VueFlow', () => {
|
||||||
const elements: Elements = [
|
const elements: Elements = [
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
import {
|
|
||||||
FlowStore,
|
|
||||||
GraphEdge,
|
|
||||||
NodeChange,
|
|
||||||
EdgeChange,
|
|
||||||
UseEdgesStateOptions,
|
|
||||||
UseEdgeState,
|
|
||||||
Edge,
|
|
||||||
Connection,
|
|
||||||
GraphNode,
|
|
||||||
UseNodesStateOptions,
|
|
||||||
UseNodesState,
|
|
||||||
} from '~/types'
|
|
||||||
import { 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 useEdgesState = (
|
|
||||||
store: FlowStore,
|
|
||||||
apply: (changes: EdgeChange[]) => GraphEdge[],
|
|
||||||
): ((options?: UseEdgesStateOptions) => UseEdgeState) => {
|
|
||||||
return ({ edges, applyDefault } = { applyDefault: true }) => {
|
|
||||||
if (edges && edges.length) store.setEdges(edges)
|
|
||||||
if (applyDefault) store.hooksOn.OnEdgesChange((e) => apply(e))
|
|
||||||
return {
|
|
||||||
edges: 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 = (
|
|
||||||
store: FlowStore,
|
|
||||||
apply: (changes: NodeChange[]) => GraphNode[],
|
|
||||||
): ((options?: UseNodesStateOptions) => UseNodesState) => {
|
|
||||||
return ({ nodes, applyDefault } = { applyDefault: true }) => {
|
|
||||||
if (nodes && nodes.length) store.setNodes(nodes)
|
|
||||||
if (applyDefault) store.hooksOn.OnNodesChange((e) => apply(e))
|
|
||||||
return {
|
|
||||||
nodes: 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
|
||||||
|
const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
|
||||||
|
|
||||||
|
export const useEdgesState = ({ edges, applyDefault }: UseEdgesStateOptions = { applyDefault: true }): UseEdgesState => {
|
||||||
|
const { store } = useVueFlow()
|
||||||
|
const applyEdges = (changes: EdgeChange[]) => applyEdgeChanges(changes, store.edges)
|
||||||
|
if (edges && edges.length) store.setEdges(edges)
|
||||||
|
if (applyDefault) store.hooksOn.OnEdgesChange((e) => applyEdges(e))
|
||||||
|
return {
|
||||||
|
edges: 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, applyDefault }: UseNodesStateOptions = { applyDefault: true }): UseNodesState => {
|
||||||
|
const { id, store } = useVueFlow()
|
||||||
|
const applyNodes = (changes: NodeChange[]) => applyNodeChanges(changes, store.nodes)
|
||||||
|
if (nodes && nodes.length) store.setNodes(nodes)
|
||||||
|
if (applyDefault) store.hooksOn.OnNodesChange((e) => applyNodes(e))
|
||||||
|
|
||||||
|
return {
|
||||||
|
nodes: 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, applyDefault }: UseElementsStateOptions = { applyDefault: true },
|
||||||
|
): UseElementsState => {
|
||||||
|
const nodesState = useNodesState({ nodes, applyDefault })
|
||||||
|
const edgesState = useEdgesState({ edges, applyDefault })
|
||||||
|
|
||||||
|
return {
|
||||||
|
...nodesState,
|
||||||
|
...edgesState,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,28 @@
|
|||||||
import { getCurrentInstance } from 'vue'
|
import { getCurrentInstance } from 'vue'
|
||||||
import { useEdgesState, useNodesState } from './useElementState'
|
import { FlowOptions, UseVueFlow } from '~/types'
|
||||||
import { EdgeChange, FlowOptions, GraphEdge, GraphNode, NodeChange, UseVueFlow } from '~/types'
|
|
||||||
import { applyChanges } from '~/utils'
|
|
||||||
import { VueFlow } from '~/context'
|
import { VueFlow } from '~/context'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
|
||||||
const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
|
|
||||||
const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
|
|
||||||
|
|
||||||
let id = 0
|
let id = 0
|
||||||
export default (options?: FlowOptions): UseVueFlow => {
|
export default (options?: FlowOptions): UseVueFlow => {
|
||||||
const currentInstance = getCurrentInstance()
|
const currentInstance = getCurrentInstance()
|
||||||
let vueFlow: UseVueFlow | false | undefined = currentInstance ? inject(VueFlow, undefined) : false
|
let vueFlow: UseVueFlow | false | undefined = currentInstance
|
||||||
|
? inject(VueFlow, undefined) ?? (currentInstance.vueFlow as UseVueFlow)
|
||||||
|
: false
|
||||||
if (!vueFlow || (vueFlow && options?.id && options.id !== vueFlow.id)) {
|
if (!vueFlow || (vueFlow && options?.id && options.id !== vueFlow.id)) {
|
||||||
const name = options?.id ?? `vue-flow-${id++}`
|
const name = options?.id ?? `vue-flow-${id++}`
|
||||||
const store = reactive(useStore(name, options))
|
const store = reactive(useStore(name, options))
|
||||||
const applyNodes = (changes: NodeChange[]) => applyNodeChanges(changes, store.nodes)
|
|
||||||
const applyEdges = (changes: EdgeChange[]) => applyEdgeChanges(changes, store.edges)
|
|
||||||
vueFlow = {
|
vueFlow = {
|
||||||
id: name,
|
id: name,
|
||||||
store,
|
store,
|
||||||
...toRefs(store),
|
...toRefs(store),
|
||||||
useNodesState: (nodes, applyDefault = true) => useNodesState(store, applyNodes)({ nodes, applyDefault }),
|
|
||||||
useEdgesState: (edges, applyDefault = true) => useEdgesState(store, applyEdges)({ edges, applyDefault }),
|
|
||||||
applyNodeChanges: applyNodes,
|
|
||||||
applyEdgeChanges: applyEdges,
|
|
||||||
...store.hooksOn,
|
...store.hooksOn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentInstance) provide(VueFlow, vueFlow)
|
if (currentInstance) {
|
||||||
|
provide(VueFlow, vueFlow)
|
||||||
|
currentInstance.vueFlow = vueFlow
|
||||||
|
}
|
||||||
|
|
||||||
return vueFlow
|
return vueFlow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export { default as useZoomPanHelper } from './composables/useZoomPanHelper'
|
|||||||
export { default as useVueFlow } from './composables/useVueFlow'
|
export { default as useVueFlow } from './composables/useVueFlow'
|
||||||
export { default as useHandle } from './composables/useHandle'
|
export { default as useHandle } from './composables/useHandle'
|
||||||
export { default as useWindow } from './composables/useWindow'
|
export { default as useWindow } from './composables/useWindow'
|
||||||
|
export * from './composables/useElementsState'
|
||||||
|
|
||||||
export * from './additional-components'
|
export * from './additional-components'
|
||||||
export * from './types'
|
export * from './types'
|
||||||
|
|||||||
Vendored
+8
@@ -1,6 +1,14 @@
|
|||||||
|
import { UseVueFlow } from '~/types'
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import { DefineComponent } from 'vue'
|
import { DefineComponent } from 'vue'
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>
|
||||||
export default component
|
export default component
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
interface ComponentInternalInstance {
|
||||||
|
vueFlow: UseVueFlow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+12
-11
@@ -126,31 +126,32 @@ export type FlowOptions<N = any, E = N> = FlowProps<N, E>
|
|||||||
type UseStateOptions = {
|
type UseStateOptions = {
|
||||||
applyDefault?: boolean
|
applyDefault?: boolean
|
||||||
}
|
}
|
||||||
export type UseNodesState = {
|
|
||||||
nodes: GraphNode[]
|
|
||||||
setNodes: FlowActions['setNodes']
|
|
||||||
addNodes: (nodes: Node[], extent?: CoordinateExtent) => GraphNode[]
|
|
||||||
OnNodesChange: FlowHooksOn['OnNodesChange']
|
|
||||||
}
|
|
||||||
export interface UseNodesStateOptions extends UseStateOptions {
|
export interface UseNodesStateOptions extends UseStateOptions {
|
||||||
nodes?: Node[]
|
nodes?: Node[]
|
||||||
}
|
}
|
||||||
export interface UseEdgesStateOptions extends UseStateOptions {
|
export interface UseEdgesStateOptions extends UseStateOptions {
|
||||||
edges?: Edge[]
|
edges?: Edge[]
|
||||||
}
|
}
|
||||||
export type UseEdgeState = {
|
export interface UseElementsStateOptions extends UseStateOptions {
|
||||||
|
edges?: Edge[]
|
||||||
|
nodes?: Node[]
|
||||||
|
}
|
||||||
|
export type UseNodesState = {
|
||||||
|
nodes: GraphNode[]
|
||||||
|
setNodes: FlowActions['setNodes']
|
||||||
|
addNodes: (nodes: Node[], extent?: CoordinateExtent) => GraphNode[]
|
||||||
|
OnNodesChange: FlowHooksOn['OnNodesChange']
|
||||||
|
}
|
||||||
|
export type UseEdgesState = {
|
||||||
edges: GraphEdge[]
|
edges: GraphEdge[]
|
||||||
setEdges: FlowActions['setEdges']
|
setEdges: FlowActions['setEdges']
|
||||||
addEdges: (params: (Edge | Connection)[]) => GraphEdge[]
|
addEdges: (params: (Edge | Connection)[]) => GraphEdge[]
|
||||||
updateEdge: (oldEdge: GraphEdge, newConnection: Connection) => GraphEdge | false
|
updateEdge: (oldEdge: GraphEdge, newConnection: Connection) => GraphEdge | false
|
||||||
OnEdgesChange: FlowHooksOn['OnEdgesChange']
|
OnEdgesChange: FlowHooksOn['OnEdgesChange']
|
||||||
}
|
}
|
||||||
|
export type UseElementsState = UseNodesState & UseEdgesState
|
||||||
export type UseVueFlow = {
|
export type UseVueFlow = {
|
||||||
id: string
|
id: string
|
||||||
store: FlowStore
|
store: FlowStore
|
||||||
useNodesState: (nodes?: Node[], applyDefault?: boolean) => UseNodesState
|
|
||||||
useEdgesState: (edges?: Edge[], applyDefault?: boolean) => UseEdgeState
|
|
||||||
applyNodeChanges: (changes: NodeChange[]) => void
|
|
||||||
applyEdgeChanges: (changes: EdgeChange[]) => void
|
|
||||||
} & FlowHooksOn &
|
} & FlowHooksOn &
|
||||||
ToRefs<FlowStore>
|
ToRefs<FlowStore>
|
||||||
|
|||||||
Reference in New Issue
Block a user