From 1e9cbc064320bc09662661843b7e819cd7a5d5bd Mon Sep 17 00:00:00 2001 From: Braks <78412429+bcakmakoglu@users.noreply.github.com> Date: Wed, 6 Apr 2022 16:22:32 +0200 Subject: [PATCH] feat(nodes): Add PositionFunc as node position type * Allows position to be set relative to another node --- package/src/store/actions.ts | 8 +++++- package/src/types/node.ts | 12 ++++++--- package/src/utils/graph.ts | 48 +++++++++++++++++++----------------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/package/src/store/actions.ts b/package/src/store/actions.ts index 857fad3d..58a48ab4 100644 --- a/package/src/store/actions.ts +++ b/package/src/store/actions.ts @@ -99,10 +99,16 @@ const createGraphNodes = (nodes: Node[], getNode: Getters['getNode'], currGraphN }) graphNodes.forEach((node) => { - if (node.parentNode && ![...graphNodes, ...currGraphNodes].find((n) => n.id === node.parentNode)) { + const nextNodes = [...graphNodes, ...currGraphNodes] + if (node.parentNode && !nextNodes.find((n) => n.id === node.parentNode)) { console.warn(`[vueflow]: Parent node ${node.parentNode} not found`) } + const position = + (node).position instanceof Function + ? (node).position(node, currGraphNodes, node.parentNode ? getNode(node.parentNode) : undefined) + : node.position + if (position) node.position = position if (node.parentNode || parentNodes[node.id]) { if (parentNodes[node.id]) { node.isParent = true diff --git a/package/src/types/node.ts b/package/src/types/node.ts index 9e40a7d3..ce83ad22 100644 --- a/package/src/types/node.ts +++ b/package/src/types/node.ts @@ -10,13 +10,17 @@ export type NodeHandleBounds = { target?: HandleElement[] } -type WidthHeight = number | `${`parent` | string}(${`+` | `-`}${number})` +type PositionFunc = ( + node: GraphNode, + currNodes: GraphNode[], + parentNode: GraphNode, +) => XYPosition type WidthFunc = (node: GraphNode) => number | string | void type HeightFunc = (node: GraphNode) => number | string | void export interface Node extends Element { - /** node position x, y */ - position: XYPosition + /** initial node position x, y */ + position: XYPosition | PositionFunc /** node type, can be a default type or a custom type */ type?: keyof DefaultNodeTypes | string /** handle position */ @@ -56,6 +60,8 @@ export interface Node extends Element { } export interface GraphNode extends Node { + /** current node position x, y */ + position: XYPosition /** absolute position in relation to parent elements + z-index */ computedPosition: XYZPosition handleBounds: NodeHandleBounds diff --git a/package/src/utils/graph.ts b/package/src/utils/graph.ts index 8f36c110..8e0fd007 100644 --- a/package/src/utils/graph.ts +++ b/package/src/utils/graph.ts @@ -62,31 +62,33 @@ export const isGraphNode = (element: Node | Edge | Connection): element is Graph isNode(element) && 'computedPosition' in element export const parseNode = (node: Node, nodeExtent: CoordinateExtent, defaults?: Partial): GraphNode => { - defaults = !isGraphNode(node) - ? { - type: node.type ?? 'default', - dimensions: { - width: 0, - height: 0, - }, - handleBounds: { - source: [], - target: [], - }, - computedPosition: { - z: 0, - ...clampPosition(node.position, nodeExtent), - }, - dragging: false, - draggable: undefined, - selectable: undefined, - connectable: undefined, - ...defaults, - } - : defaults + let defaultValues = defaults + if (!isGraphNode(node)) { + defaultValues = { + type: node.type ?? 'default', + dimensions: { + width: 0, + height: 0, + }, + handleBounds: { + source: [], + target: [], + }, + computedPosition: { + z: 0, + x: 0, + y: 0, + }, + dragging: false, + draggable: undefined, + selectable: undefined, + connectable: undefined, + ...defaults, + } + } return { - ...(defaults as GraphNode), + ...defaultValues, ...(node as GraphNode), id: node.id.toString(), }