diff --git a/src/components/Handle/Handle.vue b/src/components/Handle/Handle.vue
index a0fcb32f..e8669773 100644
--- a/src/components/Handle/Handle.vue
+++ b/src/components/Handle/Handle.vue
@@ -1,7 +1,7 @@
diff --git a/src/container/ZoomPane/ZoomPane.vue b/src/container/ZoomPane/ZoomPane.vue
index 28a2a14d..7dbb6f46 100644
--- a/src/container/ZoomPane/ZoomPane.vue
+++ b/src/container/ZoomPane/ZoomPane.vue
@@ -2,7 +2,7 @@
import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom'
import { get, invoke } from '@vueuse/core'
import { pointer, select } from 'd3-selection'
-import { FlowTransform, KeyCode, PanOnScrollMode } from '../../types'
+import { FlowInstance, FlowTransform, KeyCode, PanOnScrollMode } from '../../types'
import { useHooks, useKeyPress, useStore, useZoomPanHelper } from '../../composables'
import { clamp, onLoadGetElements, onLoadProject, onLoadToObject } from '../../utils'
@@ -186,7 +186,7 @@ store.dimensions = {
invoke(async () => {
await until(() => !isNaN(width.value) && width.value > 0 && !isNaN(height.value) && height.value > 0).toBeTruthy()
- hooks.load.trigger({
+ const instance: FlowInstance = {
fitView: (params = { padding: 0.1 }) => fitView(params),
zoomIn,
zoomOut,
@@ -195,7 +195,8 @@ invoke(async () => {
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
- })
+ }
+ hooks.load.trigger(instance)
})
watch(
diff --git a/src/context/index.ts b/src/context/index.ts
index 405cdeb8..95df9a46 100644
--- a/src/context/index.ts
+++ b/src/context/index.ts
@@ -3,4 +3,4 @@ import { ElementId, FlowHooks, FlowStore } from '~/types'
export const Store: InjectionKey = Symbol('store')
export const Hooks: InjectionKey = Symbol('hooks')
-export const NodeIdContextKey: InjectionKey = Symbol('NodeIdContext')
+export const NodeId: InjectionKey = Symbol('nodeId')
diff --git a/src/index.ts b/src/index.ts
index f838935b..f825737d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -19,11 +19,9 @@ export {
graphPosToZoomedPos,
} from './utils/graph'
export { default as useZoomPanHelper } from './composables/useZoomPanHelper'
-export { default as useStore } from './composables/useStore'
-export { default as useHooks } from './composables/useHooks'
+export { default as useVueFlow } from './composables/useVueFlow'
export { default as useHandle } from './composables/useHandle'
export { default as useKeyPress } from './composables/useKeyPress'
-export { default as useVueFlow } from './composables/useVueFlow'
export * from './additional-components'
export * from './types'
diff --git a/src/store/useFlowStore.ts b/src/store/flowStore.ts
similarity index 76%
rename from src/store/useFlowStore.ts
rename to src/store/flowStore.ts
index e769d082..08e9d756 100644
--- a/src/store/useFlowStore.ts
+++ b/src/store/flowStore.ts
@@ -1,6 +1,6 @@
import { setActivePinia, createPinia, defineStore, StoreDefinition } from 'pinia'
import diff from 'microdiff'
-import { Edge, FlowState, Node, FlowActions } from '~/types'
+import { Edge, FlowState, Node, FlowActions, Elements, NodeExtent } from '~/types'
import {
clampPosition,
getDimensions,
@@ -21,7 +21,54 @@ type NextElements = {
const pinia = createPinia()
let id = 0
-export default function useFlowStore(preloadedState: FlowState): StoreDefinition {
+const parseElements = (elements: Elements, nodes: Node[], edges: Edge[], nodeExtent: NodeExtent) => {
+ const nextElements: NextElements = {
+ nextNodes: [],
+ nextEdges: [],
+ }
+ for (const element of elements) {
+ if (isNode(element)) {
+ const storeNode = nodes.find((node) => node.id === element.id)
+
+ if (storeNode) {
+ const updatedNode: Node = {
+ ...storeNode,
+ ...element,
+ }
+ if (!updatedNode.__rf) updatedNode.__rf = {}
+
+ if (storeNode.position.x !== element.position.x || storeNode.position.y !== element.position.y) {
+ updatedNode.__rf.position = element.position
+ }
+
+ if (typeof element.type !== 'undefined' && element.type !== storeNode.type) {
+ // we reset the elements dimensions here in order to force a re-calculation of the bounds.
+ // When the type of a node changes it is possible that the number or positions of handles changes too.
+ updatedNode.__rf.width = undefined
+ }
+
+ nextElements.nextNodes.push(updatedNode)
+ } else {
+ nextElements.nextNodes.push(parseNode(element, nodeExtent))
+ }
+ } else if (isEdge(element)) {
+ const storeEdge = edges.find((se) => se.id === element.id)
+
+ if (storeEdge) {
+ nextElements.nextEdges.push({
+ ...storeEdge,
+ ...element,
+ })
+ } else {
+ nextElements.nextEdges.push(parseEdge(element))
+ }
+ }
+ }
+
+ return nextElements
+}
+
+export default function flowStore(preloadedState: FlowState): StoreDefinition {
setActivePinia(pinia)
return defineStore({
@@ -32,51 +79,7 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
getters: {},
actions: {
setElements(elements) {
- const nextElements: NextElements = {
- nextNodes: [],
- nextEdges: [],
- }
- const { nextNodes, nextEdges } = elements.reduce((res, propElement): NextElements => {
- if (isNode(propElement)) {
- const storeNode = this.nodes.find((node) => node.id === propElement.id)
-
- if (storeNode) {
- const updatedNode: Node = {
- ...storeNode,
- ...propElement,
- }
- if (!updatedNode.__rf) updatedNode.__rf = {}
-
- if (storeNode.position.x !== propElement.position.x || storeNode.position.y !== propElement.position.y) {
- updatedNode.__rf.position = propElement.position
- }
-
- if (typeof propElement.type !== 'undefined' && propElement.type !== storeNode.type) {
- // we reset the elements dimensions here in order to force a re-calculation of the bounds.
- // When the type of a node changes it is possible that the number or positions of handles changes too.
- updatedNode.__rf.width = undefined
- }
-
- res.nextNodes.push(updatedNode)
- } else {
- res.nextNodes.push(parseNode(propElement, this.nodeExtent))
- }
- } else if (isEdge(propElement)) {
- const storeEdge = this.edges.find((se) => se.id === propElement.id)
-
- if (storeEdge) {
- res.nextEdges.push({
- ...storeEdge,
- ...propElement,
- })
- } else {
- res.nextEdges.push(parseEdge(propElement))
- }
- }
-
- return res
- }, nextElements)
-
+ const { nextNodes, nextEdges } = parseElements(elements, this.nodes, this.edges, this.nodeExtent)
this.nodes = nextNodes
this.edges = nextEdges
},
@@ -257,6 +260,11 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
this.nodesConnectable = isInteractive
this.elementsSelectable = isInteractive
},
+ addElements(elements: Elements) {
+ const { nextNodes, nextEdges } = parseElements(elements, this.nodes, this.edges, this.nodeExtent)
+ this.nodes = [...this.nodes, ...nextNodes]
+ this.edges = [...this.edges, ...nextEdges]
+ },
},
})
}
diff --git a/src/store/index.ts b/src/store/index.ts
index d7f28009..c0591b49 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -1,4 +1,5 @@
import { ConnectionMode, FlowState } from '~/types'
+import { createHooks } from '~/composables'
export const initialState = (): FlowState => ({
dimensions: {
@@ -6,6 +7,8 @@ export const initialState = (): FlowState => ({
height: 0,
},
transform: [0, 0, 1],
+ nodeTypes: [],
+ edgeTypes: [],
elements: [],
nodes: [],
edges: [],
@@ -54,7 +57,10 @@ export const initialState = (): FlowState => ({
multiSelectionActive: false,
+ isReady: false,
+ hooks: createHooks(),
+
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
})
-export { default as useFlowStore } from './useFlowStore'
+export { default as useFlowStore } from './flowStore'
diff --git a/src/types/actions.ts b/src/types/actions.ts
index be2c987b..98f45af1 100644
--- a/src/types/actions.ts
+++ b/src/types/actions.ts
@@ -22,4 +22,5 @@ export interface FlowActions {
updateSize: (size: Dimensions) => void
setConnectionNodeId: (payload: SetConnectionId) => void
setInteractive: (isInteractive: boolean) => void
+ addElements: (elements: Elements) => void
}
diff --git a/src/types/store.ts b/src/types/store.ts
index 27061129..734dc5ec 100644
--- a/src/types/store.ts
+++ b/src/types/store.ts
@@ -2,17 +2,20 @@ import { Store } from 'pinia'
import { Dimensions, ElementId, Elements, Rect, SelectionRect, SnapGrid, Transform, XYPosition } from './types'
import { HandleType } from './handle'
import { ConnectionMode, OnConnectEndFunc, OnConnectFunc, OnConnectStartFunc, OnConnectStopFunc } from './connection'
-import { Edge } from './edge'
-import { Node, NodeExtent, TranslateExtent } from './node'
+import { Edge, EdgeType } from './edge'
+import { Node, NodeExtent, NodeType, TranslateExtent } from './node'
import { FlowActions } from './actions'
import { D3Selection, D3Zoom, D3ZoomHandler } from './panel'
+import { FlowHooks } from '~/types/hooks'
export interface FlowState {
dimensions: Dimensions
transform: Transform
elements: Elements
nodes: Node[]
+ nodeTypes: Record | string[]
edges: Edge[]
+ edgeTypes: Record | string[]
selectedElements?: Elements
selectedNodesBbox: Rect
@@ -50,6 +53,9 @@ export interface FlowState {
onConnectStart?: OnConnectStartFunc
onConnectStop?: OnConnectStopFunc
onConnectEnd?: OnConnectEndFunc
+
+ isReady: boolean
+ hooks: FlowHooks
}
export type FlowStore = Store