diff --git a/src/container/SelectionPane/SelectionPane.vue b/src/container/SelectionPane/SelectionPane.vue
index 69938c14..793b6118 100644
--- a/src/container/SelectionPane/SelectionPane.vue
+++ b/src/container/SelectionPane/SelectionPane.vue
@@ -3,7 +3,7 @@ import { ElementId, FlowElement, KeyCode } from '../../types'
import { useStore, useKeyPress } from '../../composables'
import NodesSelection from '../../components/NodesSelection/NodesSelection.vue'
import UserSelection from '../../components/UserSelection/UserSelection.vue'
-import { getConnectedEdges, isNode } from '../../utils'
+import { getConnectedEdges, isGraphNode } from '../../utils'
interface SelectionPaneProps {
selectionKeyCode?: KeyCode
@@ -33,7 +33,7 @@ const selectionKeyPresed = ref(false)
onMounted(() => {
useKeyPress(props.deleteKeyCode, (keyPressed) => {
if (keyPressed && store.selectedElements) {
- const selectedNodes = store.selectedElements.filter(isNode)
+ const selectedNodes = store.selectedElements.filter(isGraphNode)
const connectedEdges = getConnectedEdges(selectedNodes, store.edges)
const elementsToRemove = [...store.selectedElements, ...connectedEdges].reduce(
(res, item) => res.set(item.id, item),
diff --git a/src/container/VueFlow/VueFlow.vue b/src/container/VueFlow/VueFlow.vue
index 0668c950..e4779440 100644
--- a/src/container/VueFlow/VueFlow.vue
+++ b/src/container/VueFlow/VueFlow.vue
@@ -181,7 +181,6 @@ const transitionName = computed(() => {
{
- const updatedNode: Node = {
+ const update = (node: GraphNode, i: number) => {
+ const updatedNode: GraphNode = {
...node,
__vf: {
- width: 0,
- height: 0,
- position: { x: 0, y: 0 },
...node.__vf,
isDragging,
},
@@ -161,8 +166,8 @@ export default function flowStore(
if (!id) {
const selectedNodes = this.nodes.filter((x) => this.selectedElements?.find((sNode) => sNode?.id === x.id))
selectedNodes.forEach((node) => {
- const i = this.nodes.map((x) => x.id).indexOf((node as Node).id)
- update(node as Node, i)
+ const i = this.nodes.map((x) => x.id).indexOf(node.id)
+ update(node, i)
})
} else {
const i = this.nodes.map((x) => x.id).indexOf(id)
@@ -202,7 +207,7 @@ export default function flowStore(
this.selectedElements = nextSelectedElements
},
unsetUserSelection() {
- const selectedNodes = this.selectedElements?.filter((node) => node && isNode(node) && node.__vf) as Node[]
+ const selectedNodes = this.selectedElements?.filter((node) => node && isGraphNode(node) && node.__vf) as GraphNode[]
this.selectionActive = false
this.userSelectionRect.draw = false
@@ -243,8 +248,6 @@ export default function flowStore(
return {
...node,
__vf: {
- height: 0,
- width: 0,
...node.__vf,
position: node.__vf?.position ? clampPosition(node.__vf.position, nodeExtent) : { x: 0, y: 0 },
},
@@ -272,7 +275,7 @@ export default function flowStore(
},
async addElements(elements: Elements) {
const { nextNodes, nextEdges } = await parseElements(elements, this.nodes, this.edges, this.nodeExtent)
- this.elements = [...this.elements, ...elements]
+ this.elements = [...this.elements, ...nextNodes, ...nextEdges]
this.nodes = [...this.nodes, ...nextNodes]
this.edges = [...this.edges, ...nextEdges]
},
diff --git a/src/types/actions.ts b/src/types/actions.ts
deleted file mode 100644
index 98f45af1..00000000
--- a/src/types/actions.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Dimensions, Elements, XYPosition } from './types'
-import { NodeDiffUpdate, NodeDimensionUpdate, NodeExtent, NodePosUpdate, TranslateExtent } from './node'
-import { InitD3ZoomPayload } from './panel'
-import { SetConnectionId } from './connection'
-
-export interface FlowActions {
- setElements: (elements: Elements) => void
- updateNodeDimensions: (update: NodeDimensionUpdate) => void
- updateNodePos: (payload: NodePosUpdate) => void
- updateNodePosDiff: (payload: NodeDiffUpdate) => void
- setUserSelection: (mousePos: XYPosition) => void
- updateUserSelection: (mousePos: XYPosition) => void
- unsetUserSelection: () => void
- addSelectedElements: (elements: Elements) => void
- initD3Zoom: (payload: InitD3ZoomPayload) => void
- setMinZoom: (zoom: number) => void
- setMaxZoom: (zoom: number) => void
- setTranslateExtent: (translateExtent: TranslateExtent) => void
- setNodeExtent: (nodeExtent: NodeExtent) => void
- resetSelectedElements: () => void
- unsetNodesSelection: () => void
- updateSize: (size: Dimensions) => void
- setConnectionNodeId: (payload: SetConnectionId) => void
- setInteractive: (isInteractive: boolean) => void
- addElements: (elements: Elements) => void
-}
diff --git a/src/types/connection.ts b/src/types/connection.ts
index 6b35c5fd..6c01bce9 100644
--- a/src/types/connection.ts
+++ b/src/types/connection.ts
@@ -1,4 +1,4 @@
-import { ElementId, Position } from './types'
+import { ElementId, Position } from './flow'
import { HandleType } from './handle'
export enum ConnectionLineType {
diff --git a/src/types/edge.ts b/src/types/edge.ts
index 911f59af..88500722 100644
--- a/src/types/edge.ts
+++ b/src/types/edge.ts
@@ -1,5 +1,5 @@
import { Component, CSSProperties, DefineComponent } from 'vue'
-import { ArrowHeadType, ElementId, Position } from './types'
+import { ArrowHeadType, ElementId, Position } from './flow'
export interface Edge {
id: ElementId
diff --git a/src/types/types.ts b/src/types/flow.ts
similarity index 86%
rename from src/types/types.ts
rename to src/types/flow.ts
index 028803b4..d4361085 100644
--- a/src/types/types.ts
+++ b/src/types/flow.ts
@@ -1,15 +1,18 @@
import { CSSProperties } from 'vue'
import { Edge, EdgeTypes } from './edge'
-import { Node, NodeExtent, NodeTypes, TranslateExtent } from './node'
+import { NodeExtent, GraphNode, NodeTypes, TranslateExtent, Node } from './node'
import { ConnectionLineType, ConnectionMode } from './connection'
-import { KeyCode, PanOnScrollMode } from './panel'
+import { KeyCode, PanOnScrollMode } from './zoom'
import { FlowStore } from './store'
export type ElementId = string
-
-export type FlowElement = Node | Edge
-
-export type Elements = FlowElement[]
+export type FlowElement = GraphNode | Edge
+export type FlowElements = FlowElement[]
+export type Elements = (Node | Edge)[]
+export type NextElements = {
+ nextNodes: GraphNode[]
+ nextEdges: Edge[]
+}
export type Transform = [number, number, number]
@@ -63,7 +66,7 @@ export type FitViewParams = {
}
export type FlowExportObject = {
- elements: Elements
+ elements: FlowElements
position: [number, number]
zoom: number
}
@@ -98,14 +101,13 @@ export type FlowInstance = {
zoomTo: (zoomLevel: number) => void
fitView: FitViewFunc
project: ProjectFunc
- getElements: () => Elements
+ getElements: () => FlowElements
setTransform: (transform: FlowTransform) => void
toObject: ToObjectFunc
}
export interface FlowOptions {
id?: string
- store?: FlowStore
elements?: Elements
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
@@ -142,4 +144,5 @@ export interface FlowOptions {
storageKey?: string
loading?: Loading
worker?: boolean
+ store?: FlowStore
}
diff --git a/src/types/handle.ts b/src/types/handle.ts
index 7efa99e3..b1e89426 100644
--- a/src/types/handle.ts
+++ b/src/types/handle.ts
@@ -1,5 +1,5 @@
-import { Dimensions, ElementId, Position, XYPosition } from './types'
-import { Connection } from '~/types/connection'
+import { Dimensions, ElementId, Position, XYPosition } from './flow'
+import { Connection } from './connection'
export type HandleType = 'source' | 'target'
diff --git a/src/types/hooks.ts b/src/types/hooks.ts
index bcd74d62..8bdd5785 100644
--- a/src/types/hooks.ts
+++ b/src/types/hooks.ts
@@ -1,5 +1,5 @@
import { EventHook } from '@vueuse/core'
-import { Elements, FlowTransform, FlowInstance } from './types'
+import { FlowTransform, FlowInstance, FlowElements } from './flow'
import { Edge } from './edge'
import { Node } from './node'
import { Connection, OnConnectStartParams } from './connection'
@@ -8,7 +8,7 @@ export type FlowHook = EventHook
export interface FlowEvents {
elementClick: { event: MouseEvent; element: Node | Edge }
- elementsRemove: Elements
+ elementsRemove: FlowElements
nodeDoubleClick: { event: MouseEvent; node: Node }
nodeClick: { event: MouseEvent; node: Node }
nodeMouseEnter: { event: MouseEvent; node: Node }
@@ -29,7 +29,7 @@ export interface FlowEvents {
move: FlowTransform | undefined
moveStart: FlowTransform | undefined
moveEnd: FlowTransform | undefined
- selectionChange: Elements | null
+ selectionChange: FlowElements | null
selectionDragStart: { event: MouseEvent; nodes: Node[] }
selectionDrag: { event: MouseEvent; nodes: Node[] }
selectionDragStop: { event: MouseEvent; nodes: Node[] }
diff --git a/src/types/index.ts b/src/types/index.ts
index 3f68a791..58f9efd8 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,9 +1,8 @@
-export * from './types'
-export * from './actions'
+export * from './flow'
export * from './connection'
export * from './edge'
export * from './handle'
export * from './node'
-export * from './panel'
+export * from './zoom'
export * from './store'
export * from './hooks'
diff --git a/src/types/node.ts b/src/types/node.ts
index 731cdf41..f764935c 100644
--- a/src/types/node.ts
+++ b/src/types/node.ts
@@ -1,21 +1,22 @@
import { Component, CSSProperties, DefineComponent } from 'vue'
-import { XYPosition, ElementId, Position } from './types'
-import { HandleElement } from '~/types/handle'
+import { XYPosition, ElementId, Position } from './flow'
+import { HandleElement } from './handle'
+
+interface VFInternals {
+ position: XYPosition
+ isDragging?: boolean
+ width: number
+ height: number
+ handleBounds: {
+ source: HandleElement[] | null
+ target: HandleElement[] | null
+ }
+}
export interface Node {
id: ElementId
position: XYPosition
type?: string
- __vf?: {
- position: XYPosition
- isDragging?: boolean
- width: number
- height: number
- handleBounds?: {
- source?: HandleElement[] | null
- target?: HandleElement[] | null
- }
- }
class?: string
style?: CSSProperties
data?: T
@@ -27,6 +28,10 @@ export interface Node {
connectable?: boolean
}
+export interface GraphNode extends Node {
+ __vf: VFInternals
+}
+
export type NodePosUpdate = {
id: ElementId
pos: XYPosition
diff --git a/src/types/store.ts b/src/types/store.ts
index b23fc2ef..54572013 100644
--- a/src/types/store.ts
+++ b/src/types/store.ts
@@ -3,6 +3,7 @@ import {
Dimensions,
ElementId,
Elements,
+ FlowElements,
FlowInstance,
FlowOptions,
Rect,
@@ -10,20 +11,26 @@ import {
SnapGrid,
Transform,
XYPosition,
-} from './types'
+} from './flow'
import { HandleType } from './handle'
-import { ConnectionMode, OnConnectEndFunc, OnConnectFunc, OnConnectStartFunc, OnConnectStopFunc } from './connection'
+import {
+ ConnectionMode,
+ OnConnectEndFunc,
+ OnConnectFunc,
+ OnConnectStartFunc,
+ OnConnectStopFunc,
+ SetConnectionId,
+} from './connection'
import { Edge, EdgeComponent } from './edge'
-import { Node, NodeComponent, NodeExtent, TranslateExtent } from './node'
-import { FlowActions } from './actions'
-import { D3Selection, D3Zoom, D3ZoomHandler } from './panel'
+import { NodeComponent, NodeDiffUpdate, NodeDimensionUpdate, NodeExtent, GraphNode, NodePosUpdate, TranslateExtent } from './node'
+import { D3Selection, D3Zoom, D3ZoomHandler, InitD3ZoomPayload } from './zoom'
import { FlowHooks } from './hooks'
export interface FlowState extends FlowOptions {
- elements: Elements
- nodes: Node[]
+ elements: FlowElements
+ nodes: GraphNode[]
edges: Edge[]
- selectedElements?: Elements
+ selectedElements?: FlowElements
selectedNodesBbox: Rect
d3Zoom?: D3Zoom
@@ -66,10 +73,32 @@ export interface FlowState extends FlowOptions {
vueFlowVersion: string
}
+export interface FlowActions {
+ setElements: (elements: Elements) => Promise
+ updateNodeDimensions: (update: NodeDimensionUpdate) => void
+ updateNodePos: (payload: NodePosUpdate) => void
+ updateNodePosDiff: (payload: NodeDiffUpdate) => void
+ setUserSelection: (mousePos: XYPosition) => void
+ updateUserSelection: (mousePos: XYPosition) => void
+ unsetUserSelection: () => void
+ addSelectedElements: (elements: FlowElements) => void
+ initD3Zoom: (payload: InitD3ZoomPayload) => void
+ setMinZoom: (zoom: number) => void
+ setMaxZoom: (zoom: number) => void
+ setTranslateExtent: (translateExtent: TranslateExtent) => void
+ setNodeExtent: (nodeExtent: NodeExtent) => void
+ resetSelectedElements: () => void
+ unsetNodesSelection: () => void
+ updateSize: (size: Dimensions) => void
+ setConnectionNodeId: (payload: SetConnectionId) => void
+ setInteractive: (isInteractive: boolean) => void
+ addElements: (elements: Elements) => Promise
+}
+
export interface FlowGetters {
getEdgeTypes: () => Record
getNodeTypes: () => Record
- getNodes: () => Node[]
+ getNodes: () => GraphNode[]
getEdges: () => Edge[]
}
diff --git a/src/types/panel.ts b/src/types/zoom.ts
similarity index 99%
rename from src/types/panel.ts
rename to src/types/zoom.ts
index 621359d3..5dbf9eba 100644
--- a/src/types/panel.ts
+++ b/src/types/zoom.ts
@@ -1,5 +1,5 @@
import { Selection, ZoomBehavior } from 'd3'
-import { FitViewFunc, FlowTransform, Rect, XYPosition } from './types'
+import { FitViewFunc, FlowTransform, Rect, XYPosition } from './flow'
export type D3Zoom = ZoomBehavior
export type D3Selection = Selection
diff --git a/src/container/EdgeRenderer/utils.ts b/src/utils/edge.ts
similarity index 80%
rename from src/container/EdgeRenderer/utils.ts
rename to src/utils/edge.ts
index c166590e..0a07e262 100644
--- a/src/container/EdgeRenderer/utils.ts
+++ b/src/utils/edge.ts
@@ -1,11 +1,11 @@
-import { Edge, EdgePositions, ElementId, HandleElement, Node, Position, Transform, XYPosition } from '../../types'
-import { rectToBox } from '~/utils'
+import { rectToBox } from './graph'
+import { Edge, EdgePositions, ElementId, GraphNode, HandleElement, Position, Transform, XYPosition } from '~/types'
-export function getHandlePosition(position: Position, node: Node, handle: any | null = null): XYPosition {
- const x = (handle?.x || 0) + node.__vf?.position?.x
- const y = (handle?.y || 0) + node.__vf?.position?.y
- const width = handle?.width || node.__vf?.width
- const height = handle?.height || node.__vf?.height
+export function getHandlePosition(position: Position, node: GraphNode, handle: any | null = null): XYPosition {
+ const x = (handle?.x || 0) + node.__vf.position.x
+ const y = (handle?.y || 0) + node.__vf.position.y
+ const width = handle?.width || node.__vf.width
+ const height = handle?.height || node.__vf.height
switch (position) {
case Position.Top:
@@ -47,10 +47,10 @@ export function getHandle(bounds: HandleElement[], handleId: ElementId | null):
}
export const getEdgePositions = (
- sourceNode: Node,
+ sourceNode: GraphNode,
sourceHandle: HandleElement | unknown,
sourcePosition: Position,
- targetNode: Node,
+ targetNode: GraphNode,
targetHandle: HandleElement | unknown,
targetPosition: Position,
): EdgePositions => {
@@ -104,11 +104,11 @@ export function isEdgeVisible({ sourcePos, targetPos, width, height, transform }
}
type SourceTargetNode = {
- sourceNode: Node
- targetNode: Node
+ sourceNode: GraphNode
+ targetNode: GraphNode
}
-export const getSourceTargetNodes = (edge: Edge, nodes: Node[]): SourceTargetNode => {
+export const getSourceTargetNodes = (edge: Edge, nodes: GraphNode[]): SourceTargetNode => {
return nodes.reduce(
(res, node) => {
if (node.id === edge.source) {
diff --git a/src/utils/graph.ts b/src/utils/graph.ts
index ddb97918..33d71e71 100644
--- a/src/utils/graph.ts
+++ b/src/utils/graph.ts
@@ -12,12 +12,20 @@ import {
NodeExtent,
Dimensions,
FlowStore,
+ GraphNode,
+ FlowElements,
+ FlowElement,
} from '~/types'
import { useWindow } from '~/composables'
+const isHTMLElement = (el: EventTarget): el is HTMLElement => ('nodeName' || 'hasAttribute') in el
+
export const isInputDOMNode = (e: KeyboardEvent | MouseEvent): boolean => {
- const target = e.target as HTMLElement
- return ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName) || target.hasAttribute('contentEditable')
+ const target = e.target
+ if (target && isHTMLElement(target)) {
+ return ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName) || target.hasAttribute('contentEditable')
+ }
+ return false
}
export const getDimensions = (node: HTMLElement): Dimensions => ({
@@ -40,40 +48,30 @@ export const getHostForElement = (element: HTMLElement): Document => {
else return window.document
}
-export const isEdge = (element: Node | Connection | Edge): element is Edge =>
+export const isEdge = (element: Node | FlowElement | Connection): element is Edge =>
'id' in element && 'source' in element && 'target' in element
-export const isNode = (element: Node | Connection | Edge): element is Node =>
+export const isNode = (element: Node | FlowElement | Connection): element is Node =>
'id' in element && !('source' in element) && !('target' in element)
-export const getOutgoers = (node: Node, elements: Elements): Node[] => {
- if (!isNode(node)) {
- return []
- }
+export const isGraphNode = (element: Node | FlowElement | Connection): element is GraphNode =>
+ isNode(element) && '__vf' in element
- const outgoerIds = elements.filter((e) => isEdge(e) && e.source === node.id).map((e) => (e as Edge).target)
- return elements.filter((e) => outgoerIds.includes(e.id)) as Node[]
+const getConnectedElements = (node: GraphNode, elements: Elements, dir: 'source' | 'target') => {
+ if (!isNode(node)) return []
+ const ids = elements.filter((e) => isEdge(e) && e.source === node.id).map((e) => isEdge(e) && e[dir])
+ return elements.filter((e) => ids.includes(e.id))
}
+export const getOutgoers = (node: GraphNode, elements: Elements) => getConnectedElements(node, elements, 'target')
-export const getIncomers = (node: Node, elements: Elements): Node[] => {
- if (!isNode(node)) {
- return []
- }
+export const getIncomers = (node: GraphNode, elements: Elements) => getConnectedElements(node, elements, 'source')
- const incomersIds = elements.filter((e) => isEdge(e) && e.target === node.id).map((e) => (e as Edge).source)
- return elements.filter((e) => incomersIds.includes(e.id)) as Node[]
-}
-
-export const removeElements = (elementsToRemove: Elements, elements: Elements): Elements => {
+export const removeElements = (elementsToRemove: Elements, elements: Elements) => {
const nodeIdsToRemove = elementsToRemove.map((n) => n.id)
return elements.filter((element) => {
- const edgeElement = element as Edge
- return !(
- nodeIdsToRemove.includes(element.id) ||
- nodeIdsToRemove.includes(edgeElement.target) ||
- nodeIdsToRemove.includes(edgeElement.source)
- )
+ const { target, source } = isEdge(element) ? element : { target: '', source: '' }
+ return !(nodeIdsToRemove.includes(element.id) || nodeIdsToRemove.includes(target) || nodeIdsToRemove.includes(source))
})
}
@@ -91,13 +89,13 @@ const connectionExists = (edge: Edge, elements: Elements) => {
)
}
-export const addEdge = (edgeParams: Edge | Connection, elements: Elements): Elements => {
+export const addEdge = (edgeParams: Edge | Connection, elements: Elements) => {
if (!edgeParams.source || !edgeParams.target) {
console.log("Can't create edge. An edge needs a source and a target.")
return elements
}
- let edge: Edge
+ let edge
if (isEdge(edgeParams)) {
edge = { ...edgeParams }
} else {
@@ -114,13 +112,13 @@ export const addEdge = (edgeParams: Edge | Connection, elements: Elements): Elem
return elements.concat(edge)
}
-export const updateEdge = (oldEdge: Edge, newConnection: Connection, elements: Elements): Elements => {
+export const updateEdge = (oldEdge: Edge, newConnection: Connection, elements: Elements) => {
if (!newConnection.source || !newConnection.target) {
console.warn("Can't create new edge. An edge needs a source and a target.")
return elements
}
- const foundEdge = elements.find((e) => isEdge(e) && e.id === oldEdge.id) as Edge
+ const foundEdge = elements.find((e) => isEdge(e) && e.id === oldEdge.id)
if (!foundEdge) {
console.warn(`The old edge with id=${oldEdge.id} does not exist.`)
@@ -128,14 +126,14 @@ export const updateEdge = (oldEdge: Edge, newConnection: Connection, elements: E
}
// Remove old edge and create the new edge with parameters of old edge.
- const edge = {
+ const edge: Edge = {
...oldEdge,
id: getEdgeId(newConnection),
source: newConnection.source,
target: newConnection.target,
sourceHandle: newConnection.sourceHandle,
targetHandle: newConnection.targetHandle,
- } as Edge
+ }
return elements.filter((e) => e.id !== oldEdge.id).concat(edge)
}
@@ -145,7 +143,7 @@ export const pointToRendererPoint = (
[tx, ty, tScale]: Transform,
snapToGrid: boolean,
[snapX, snapY]: [number, number],
-): XYPosition => {
+) => {
const position: XYPosition = {
x: (x - tx) / tScale,
y: (y - ty) / tScale,
@@ -161,12 +159,10 @@ export const pointToRendererPoint = (
return position
}
-export const onLoadProject =
- (currentStore: FlowStore) =>
- (position: XYPosition): XYPosition =>
- pointToRendererPoint(position, currentStore.transform, currentStore.snapToGrid, currentStore.snapGrid)
+export const onLoadProject = (currentStore: FlowStore) => (position: XYPosition) =>
+ pointToRendererPoint(position, currentStore.transform, currentStore.snapToGrid, currentStore.snapGrid)
-export const parseNode = (node: Node, nodeExtent: NodeExtent): Node => ({
+export const parseNode = (node: Node, nodeExtent: NodeExtent): GraphNode => ({
...node,
id: node.id.toString(),
type: node.type || 'default',
@@ -174,7 +170,10 @@ export const parseNode = (node: Node, nodeExtent: NodeExtent): Node => ({
position: clampPosition(node.position, nodeExtent),
width: 0,
height: 0,
- handleBounds: {},
+ handleBounds: {
+ source: null,
+ target: null,
+ },
isDragging: false,
},
})
@@ -210,10 +209,9 @@ export const boxToRect = ({ x, y, x2, y2 }: Box): Rect => ({
height: y2 - y,
})
-export const getBoundsofRects = (rect1: Rect, rect2: Rect): Rect =>
- boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)))
+export const getBoundsofRects = (rect1: Rect, rect2: Rect) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)))
-export const getRectOfNodes = (nodes: Node[]): Rect => {
+export const getRectOfNodes = (nodes: GraphNode[]) => {
const box = nodes.reduce(
(currBox, { __vf: { position = { x: 0, y: 0 }, width = 0, height = 0 } = {} }) =>
getBoundsOfBoxes(
@@ -235,7 +233,7 @@ export const graphPosToZoomedPos = ({ x, y }: XYPosition, [tx, ty, tScale]: Tran
y: y * tScale + ty,
})
-export const getNodesInside = (nodes: Node[], rect: Rect, [tx, ty, tScale]: Transform = [0, 0, 1], partially = false): Node[] => {
+export const getNodesInside = (nodes: GraphNode[], rect: Rect, [tx, ty, tScale]: Transform = [0, 0, 1], partially = false) => {
const rBox = rectToBox({
x: (rect.x - tx) / tScale,
y: (rect.y - ty) / tScale,
@@ -266,13 +264,12 @@ export const getNodesInside = (nodes: Node[], rect: Rect, [tx, ty, tScale]: Tran
})
}
-export const getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[] => {
+export const getConnectedEdges = (nodes: GraphNode[], edges: Edge[]) => {
const nodeIds = nodes.map((node) => node.id)
-
return edges.filter((edge) => nodeIds.includes(edge.source) || nodeIds.includes(edge.target))
}
-export const onLoadGetElements = (currentStore: FlowStore) => (): Elements => currentStore.elements
+export const onLoadGetElements = (currentStore: FlowStore) => (): FlowElements => currentStore.elements
export const onLoadToObject = (currentStore: FlowStore) => (): FlowExportObject => {
// we have to stringify/parse so objects containing refs (like nodes and edges) can potentially be saved in a storage
diff --git a/src/utils/index.ts b/src/utils/index.ts
index b8ade72c..4c7950a6 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1 +1,4 @@
+export * from './edge'
export * from './graph'
+export * from './node'
+export * from './store'
diff --git a/src/components/Nodes/utils.ts b/src/utils/node.ts
similarity index 94%
rename from src/components/Nodes/utils.ts
rename to src/utils/node.ts
index 163bbde6..b82cc4de 100644
--- a/src/components/Nodes/utils.ts
+++ b/src/utils/node.ts
@@ -1,5 +1,5 @@
import { HandleElement, Position } from '~/types'
-import { getDimensions } from '~/utils'
+import { getDimensions } from '~/utils/graph'
export const getHandleBoundsByHandleType = (
selector: string,
@@ -19,7 +19,7 @@ export const getHandleBoundsByHandleType = (
const bounds = handle.getBoundingClientRect()
const dimensions = getDimensions(handle)
const handleId = handle.getAttribute('data-handleid')
- const handlePosition = handle.getAttribute('data-handlepos') as unknown as Position
+ const handlePosition = handle.getAttribute('data-handlepos') as Position
return {
id: handleId,
diff --git a/src/store/utils.ts b/src/utils/store.ts
similarity index 85%
rename from src/store/utils.ts
rename to src/utils/store.ts
index cb1b1e2c..d974c493 100644
--- a/src/store/utils.ts
+++ b/src/utils/store.ts
@@ -1,15 +1,20 @@
import { Component } from 'vue'
-import { ConnectionMode, Edge, EdgeProps, Elements, FlowState, Node, NodeExtent, NodeProps, PanOnScrollMode } from '~/types'
-import { isEdge, isNode, parseEdge, parseNode } from '~/utils'
-import { DefaultNode, InputNode, OutputNode } from '~/components/Nodes'
-import { BezierEdge, SmoothStepEdge, StepEdge, StraightEdge } from '~/components/Edges'
+import { isEdge, isNode, parseEdge, parseNode } from './graph'
+import {
+ ConnectionMode,
+ Edge,
+ EdgeProps,
+ Elements,
+ FlowState,
+ NextElements,
+ NodeExtent,
+ GraphNode,
+ NodeProps,
+ PanOnScrollMode,
+} from '~/types'
+import { DefaultNode, InputNode, OutputNode, BezierEdge, SmoothStepEdge, StepEdge, StraightEdge } from '~/components'
import { createHooks } from '~/composables'
-export type NextElements = {
- nextNodes: Node[]
- nextEdges: Edge[]
-}
-
export const defaultNodeTypes: Record> = {
input: InputNode,
default: DefaultNode,
@@ -94,7 +99,7 @@ export const initialState = (): FlowState => ({
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
})
-export const parseElements = async (elements: Elements, nodes: Node[], edges: Edge[], nodeExtent: NodeExtent) =>
+export const parseElements = async (elements: Elements, nodes: GraphNode[], edges: Edge[], nodeExtent: NodeExtent) =>
new Promise((resolve) => {
const nextElements: NextElements = {
nextNodes: [],
@@ -105,20 +110,20 @@ export const parseElements = async (elements: Elements, nodes: Node[], edges: Ed
const storeNode = nodes[nodes.map((x) => x.id).indexOf(element.id)]
if (storeNode) {
- const updatedNode: Node = {
+ const updatedNode: GraphNode = {
...storeNode,
...element,
}
- if (!updatedNode.__vf) updatedNode.__vf = {}
+ if (!updatedNode.__vf) updatedNode.__vf = {} as any
if (storeNode.position.x !== element.position.x || storeNode.position.y !== element.position.y) {
- updatedNode.__vf.position = element.position
+ updatedNode.__vf!.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.__vf.width = undefined
+ updatedNode.__vf!.width = 0
}
nextElements.nextNodes.push(updatedNode)
diff --git a/src/workers/parseElements.ts b/src/workers/parseElements.ts
index a3f86846..a6edad77 100644
--- a/src/workers/parseElements.ts
+++ b/src/workers/parseElements.ts
@@ -1,7 +1,7 @@
-import { Connection, Edge, Elements, Node, NodeExtent, XYPosition } from '~/types'
+import { Connection, Edge, Elements, Node, NodeExtent, GraphNode, XYPosition, NextElements, FlowElement } from '~/types'
export default () =>
- useWebWorkerFn((elements: Elements, nodes: Node[], edges: Edge[], nodeExtent: NodeExtent) => {
+ useWebWorkerFn((elements: Elements, nodes: GraphNode[], edges: Edge[], nodeExtent: NodeExtent): NextElements => {
const clamp = (val: number, min = 0, max = 1): number => Math.min(Math.max(val, min), max)
const clampPosition = (position: XYPosition, extent: NodeExtent): XYPosition => ({
@@ -9,14 +9,14 @@ export default () =>
y: clamp(position.y, extent[0][1], extent[1][1]),
})
- const parseNode = (node: Node, nodeExtent: NodeExtent): Node =>
- Object.assign(node, {
+ const parseNode = (node: Node, nodeExtent: NodeExtent): GraphNode =>
+ Object.assign(node as GraphNode, {
id: node.id.toString(),
type: node.type || 'default',
__vf: {
position: clampPosition(node.position, nodeExtent),
- width: undefined,
- height: undefined,
+ width: 0,
+ height: 0,
handleBounds: {},
isDragging: false,
},
@@ -32,13 +32,13 @@ export default () =>
type: edge.type || 'default',
})
- const isEdge = (element: Node | Connection | Edge): element is Edge =>
+ const isEdge = (element: Node | FlowElement | Connection): element is Edge =>
'id' in element && 'source' in element && 'target' in element
- const isNode = (element: Node | Connection | Edge): element is Node =>
+ const isNode = (element: Node | FlowElement | Connection): element is Node =>
'id' in element && !('source' in element) && !('target' in element)
- const nextElements: any = {
+ const nextElements: NextElements = {
nextNodes: [],
nextEdges: [],
}
@@ -48,17 +48,17 @@ export default () =>
const storeNode = nodes[nodes.map((x) => x.id).indexOf(element.id)]
if (storeNode) {
- const updatedNode: Node = Object.assign(storeNode, element)
- if (!updatedNode.__vf) updatedNode.__vf = {}
+ const updatedNode = Object.assign(storeNode, element)
+ if (!updatedNode.__vf) updatedNode.__vf = {} as any
if (storeNode.position.x !== element.position.x || storeNode.position.y !== element.position.y) {
- updatedNode.__vf.position = element.position
+ updatedNode.__vf!.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.__vf.width = undefined
+ updatedNode.__vf!.width = 0
}
nextElements.nextNodes.push(updatedNode)