diff --git a/packages/core/src/store/actions.ts b/packages/core/src/store/actions.ts index ca5b2b07..2150829c 100644 --- a/packages/core/src/store/actions.ts +++ b/packages/core/src/store/actions.ts @@ -408,10 +408,10 @@ export function useActions( return res } - const storedEdge = findEdge(edge.id) + const existingEdge = findEdge(edge.id) res.push({ - ...parseEdge(edge, Object.assign({}, storedEdge, state.defaultEdgeOptions)), + ...parseEdge(edge, existingEdge, state.defaultEdgeOptions), sourceNode, targetNode, }) @@ -459,15 +459,8 @@ export function useActions( ) : nextEdges - const changes = validEdges.reduce((edgeChanges, param) => { - const edge = addEdgeToStore( - { - ...param, - ...state.defaultEdgeOptions, - }, - state.edges, - state.hooks.error.trigger, - ) + const changes = validEdges.reduce((edgeChanges, connection) => { + const edge = addEdgeToStore(connection, state.edges, state.hooks.error.trigger, state.defaultEdgeOptions) if (edge) { const sourceNode = findNode(edge.source)! diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index 056fd22d..1930a0a5 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -97,64 +97,61 @@ export function isRect(obj: any): obj is Rect { return isNumeric(obj.width) && isNumeric(obj.height) && isNumeric(obj.x) && isNumeric(obj.y) } -export function parseNode(node: Node, defaults: Partial = {}): GraphNode { - let initialState = defaults +export function parseNode(node: Node, existingNode?: GraphNode, parentNode?: string): GraphNode { + const initialState = { + id: node.id.toString(), + type: node.type ?? 'default', + dimensions: markRaw({ + width: 0, + height: 0, + }), + handleBounds: { + source: [], + target: [], + }, + computedPosition: markRaw({ + z: 0, + ...node.position, + }), + draggable: undefined, + selectable: undefined, + connectable: undefined, + focusable: undefined, + selected: false, + dragging: false, + resizing: false, + initialized: false, + isParent: false, + position: { + x: 0, + y: 0, + }, + data: isDef(node.data) ? node.data : {}, + events: markRaw(isDef(node.events) ? node.events : {}), + } as GraphNode - if (!isGraphNode(node)) { - initialState = { - type: node.type ?? defaults.type ?? 'default', - dimensions: markRaw({ - width: 0, - height: 0, - }), - handleBounds: { - source: [], - target: [], - }, - computedPosition: markRaw({ - z: 0, - ...node.position, - }), - draggable: undefined, - selectable: undefined, - connectable: undefined, - focusable: undefined, - selected: false, - dragging: false, - resizing: false, - initialized: false, - ...defaults, - data: isDef(node.data) ? node.data : {}, - events: markRaw(isDef(node.events) ? node.events : {}), - } - } - - return Object.assign({}, initialState, node, { id: node.id.toString() }) as GraphNode + return Object.assign(existingNode ?? initialState, node, { id: node.id.toString(), parentNode }) as GraphNode } -export function parseEdge(edge: Edge, defaults: Partial = {}): GraphEdge { - const events = isDef(edge.events) ? edge.events : defaults.events && isDef(defaults.events) ? defaults.events : {} - const data = isDef(edge.data) ? edge.data : defaults.data && isDef(defaults.data) ? defaults.data : {} +export function parseEdge(edge: Edge, existingEdge?: GraphEdge, defaultEdgeOptions?: DefaultEdgeOptions): GraphEdge { + const initialState = { + id: edge.id.toString(), + type: edge.type ?? existingEdge?.type ?? 'default', + source: edge.source.toString(), + target: edge.target.toString(), + sourceHandle: edge.sourceHandle?.toString(), + targetHandle: edge.targetHandle?.toString(), + updatable: edge.updatable ?? defaultEdgeOptions?.updatable, + selectable: edge.selectable ?? defaultEdgeOptions?.selectable, + focusable: edge.focusable ?? defaultEdgeOptions?.focusable, + data: isDef(edge.data) ? edge.data : {}, + events: markRaw(isDef(edge.events) ? edge.events : {}), + label: edge.label ?? '', + interactionWidth: edge.interactionWidth ?? defaultEdgeOptions?.interactionWidth, + ...(defaultEdgeOptions ?? {}), + } as GraphEdge - defaults = !isGraphEdge(edge) - ? ({ - ...defaults, - sourceHandle: (edge.sourceHandle ? edge.sourceHandle.toString() : undefined) || defaults.sourceHandle, - targetHandle: (edge.targetHandle ? edge.targetHandle.toString() : undefined) || defaults.targetHandle, - type: edge.type ?? defaults.type ?? 'default', - source: edge.source.toString() || defaults.source, - target: edge.target.toString() || defaults.target, - updatable: edge.updatable ?? defaults.updatable, - selectable: edge.selectable ?? defaults.selectable, - focusable: edge.focusable ?? defaults.focusable, - data, - events: markRaw(events), - label: (edge.label && typeof edge.label !== 'string' ? markRaw(edge.label) : edge.label) || defaults.label, - interactionWidth: edge.interactionWidth || defaults.interactionWidth, - } as GraphEdge) - : defaults - - return Object.assign({}, defaults, edge, { id: edge.id.toString() }) as GraphEdge + return Object.assign(existingEdge ?? initialState, edge, { id: edge.id.toString() }) as GraphEdge } function getConnectedElements( @@ -254,7 +251,7 @@ export function addEdge(edgeParams: Edge | Connection, elements: Elements, defau } as Edge } - edge = parseEdge(edge, defaults) + edge = parseEdge(edge, undefined, defaults) if (connectionExists(edge, elements)) { return elements diff --git a/packages/core/src/utils/store.ts b/packages/core/src/utils/store.ts index 4fb0c09a..00affcee 100644 --- a/packages/core/src/utils/store.ts +++ b/packages/core/src/utils/store.ts @@ -1,5 +1,5 @@ import { markRaw, unref } from 'vue' -import type { Actions, Connection, ConnectionLookup, Edge, GraphEdge, GraphNode, Node, State } from '../types' +import type { Actions, Connection, ConnectionLookup, DefaultEdgeOptions, Edge, GraphEdge, GraphNode, Node, State } from '../types' import { ErrorCode, VueFlowError, connectionExists, getEdgeId, isEdge, isNode, parseEdge, parseNode } from '.' type NonUndefined = T extends undefined ? never : T @@ -10,7 +10,12 @@ export function isDef(val: T): val is NonUndefined { return typeof unrefVal !== 'undefined' } -export function addEdgeToStore(edgeParams: Edge | Connection, edges: Edge[], triggerError: State['hooks']['error']['trigger']) { +export function addEdgeToStore( + edgeParams: Edge | Connection, + edges: Edge[], + triggerError: State['hooks']['error']['trigger'], + defaultEdgeOptions?: DefaultEdgeOptions, +): GraphEdge | false { if (!edgeParams.source || !edgeParams.target) { triggerError(new VueFlowError(ErrorCode.EDGE_INVALID, (edgeParams as Edge).id)) return false @@ -26,7 +31,7 @@ export function addEdgeToStore(edgeParams: Edge | Connection, edges: Edge[], tri } as Edge } - edge = parseEdge(edge) + edge = parseEdge(edge, undefined, defaultEdgeOptions) if (connectionExists(edge, edges)) { return false @@ -79,17 +84,17 @@ export function createGraphNodes( ) { const parentNodes: Record = {} - const graphNodes = nodes.reduce((nextNodes, node) => { + const graphNodes = nodes.reduce((nextNodes, node, currentIndex) => { // make sure we don't try to add invalid nodes if (!isNode(node)) { - triggerError(new VueFlowError(ErrorCode.NODE_INVALID)) + triggerError( + new VueFlowError(ErrorCode.NODE_INVALID, (node as undefined | Record)?.id) || + `[ID UNKNOWN|INDEX ${currentIndex}]`, + ) return nextNodes } - const parsed = parseNode(node, { - ...findNode(node.id), - parentNode: node.parentNode, - }) + const parsed = parseNode(node, findNode(node.id), node.parentNode) if (node.parentNode) { parentNodes[node.parentNode] = true