feat(nodes): Add PositionFunc as node position type

* Allows position to be set relative to another node
This commit is contained in:
Braks
2022-04-11 11:30:10 +02:00
parent 342d0305a6
commit 1e9cbc0643
3 changed files with 41 additions and 27 deletions
+7 -1
View File
@@ -99,10 +99,16 @@ const createGraphNodes = (nodes: Node[], getNode: Getters['getNode'], currGraphN
}) })
graphNodes.forEach((node) => { 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`) console.warn(`[vueflow]: Parent node ${node.parentNode} not found`)
} }
const position =
(<any>node).position instanceof Function
? (<any>node).position(node, currGraphNodes, node.parentNode ? getNode(node.parentNode) : undefined)
: node.position
if (position) node.position = position
if (node.parentNode || parentNodes[node.id]) { if (node.parentNode || parentNodes[node.id]) {
if (parentNodes[node.id]) { if (parentNodes[node.id]) {
node.isParent = true node.isParent = true
+9 -3
View File
@@ -10,13 +10,17 @@ export type NodeHandleBounds = {
target?: HandleElement[] target?: HandleElement[]
} }
type WidthHeight = number | `${`parent` | string}(${`+` | `-`}${number})` type PositionFunc = <Data = ElementData>(
node: GraphNode<Data>,
currNodes: GraphNode<Data>[],
parentNode: GraphNode<Data>,
) => XYPosition
type WidthFunc = <Data = ElementData>(node: GraphNode<Data>) => number | string | void type WidthFunc = <Data = ElementData>(node: GraphNode<Data>) => number | string | void
type HeightFunc = <Data = ElementData>(node: GraphNode<Data>) => number | string | void type HeightFunc = <Data = ElementData>(node: GraphNode<Data>) => number | string | void
export interface Node<Data = ElementData> extends Element<Data> { export interface Node<Data = ElementData> extends Element<Data> {
/** node position x, y */ /** initial node position x, y */
position: XYPosition position: XYPosition | PositionFunc
/** node type, can be a default type or a custom type */ /** node type, can be a default type or a custom type */
type?: keyof DefaultNodeTypes | string type?: keyof DefaultNodeTypes | string
/** handle position */ /** handle position */
@@ -56,6 +60,8 @@ export interface Node<Data = ElementData> extends Element<Data> {
} }
export interface GraphNode<Data = ElementData> extends Node<Data> { export interface GraphNode<Data = ElementData> extends Node<Data> {
/** current node position x, y */
position: XYPosition
/** absolute position in relation to parent elements + z-index */ /** absolute position in relation to parent elements + z-index */
computedPosition: XYZPosition computedPosition: XYZPosition
handleBounds: NodeHandleBounds handleBounds: NodeHandleBounds
+25 -23
View File
@@ -62,31 +62,33 @@ export const isGraphNode = (element: Node | Edge | Connection): element is Graph
isNode(element) && 'computedPosition' in element isNode(element) && 'computedPosition' in element
export const parseNode = (node: Node, nodeExtent: CoordinateExtent, defaults?: Partial<GraphNode>): GraphNode => { export const parseNode = (node: Node, nodeExtent: CoordinateExtent, defaults?: Partial<GraphNode>): GraphNode => {
defaults = !isGraphNode(node) let defaultValues = defaults
? { if (!isGraphNode(node)) {
type: node.type ?? 'default', defaultValues = {
dimensions: { type: node.type ?? 'default',
width: 0, dimensions: {
height: 0, width: 0,
}, height: 0,
handleBounds: { },
source: [], handleBounds: {
target: [], source: [],
}, target: [],
computedPosition: { },
z: 0, computedPosition: {
...clampPosition(node.position, nodeExtent), z: 0,
}, x: 0,
dragging: false, y: 0,
draggable: undefined, },
selectable: undefined, dragging: false,
connectable: undefined, draggable: undefined,
...defaults, selectable: undefined,
} connectable: undefined,
: defaults ...defaults,
}
}
return { return {
...(defaults as GraphNode), ...defaultValues,
...(node as GraphNode), ...(node as GraphNode),
id: node.id.toString(), id: node.id.toString(),
} }