refactor(nodes)!: Change children API to parentNode API
* instead of passing a children arr, pass a parentNode id * allows for easier adding of new child nodes in options api
This commit is contained in:
@@ -12,13 +12,12 @@ const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({
|
||||
position: { x: 100, y: 100 },
|
||||
class: 'light',
|
||||
style: { backgroundColor: 'rgba(255, 0, 0, 0.8)', width: '200px', height: '200px' },
|
||||
children: [
|
||||
{
|
||||
id: '2a',
|
||||
label: 'Node 2a',
|
||||
position: { x: 10, y: 50 },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2a',
|
||||
label: 'Node 2a',
|
||||
position: { x: 10, y: 50 },
|
||||
parentNode: '2',
|
||||
},
|
||||
{ id: '3', label: 'Node 3', position: { x: 320, y: 100 }, class: 'light' },
|
||||
{
|
||||
@@ -27,36 +26,36 @@ const { onConnect, nodes, edges, addEdges, addNodes } = useVueFlow({
|
||||
position: { x: 320, y: 200 },
|
||||
class: 'light',
|
||||
style: { backgroundColor: 'rgba(255, 0, 0, 0.7)', width: '300px', height: '300px' },
|
||||
children: [
|
||||
{
|
||||
id: '4a',
|
||||
label: 'Node 4a',
|
||||
position: { x: 15, y: 65 },
|
||||
class: 'light',
|
||||
extent: 'parent',
|
||||
},
|
||||
{
|
||||
id: '4b',
|
||||
label: 'Node 4b',
|
||||
position: { x: 15, y: 120 },
|
||||
class: 'light',
|
||||
style: { backgroundColor: 'rgba(255, 0, 255, 0.7)', height: '150px', width: '270px' },
|
||||
children: [
|
||||
{
|
||||
id: '4b1',
|
||||
label: 'Node 4b1',
|
||||
position: { x: 20, y: 40 },
|
||||
class: 'light',
|
||||
},
|
||||
{
|
||||
id: '4b2',
|
||||
label: 'Node 4b2',
|
||||
position: { x: 100, y: 100 },
|
||||
class: 'light',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '4a',
|
||||
label: 'Node 4a',
|
||||
position: { x: 15, y: 65 },
|
||||
class: 'light',
|
||||
extent: 'parent',
|
||||
parentNode: '4',
|
||||
},
|
||||
{
|
||||
id: '4b',
|
||||
label: 'Node 4b',
|
||||
position: { x: 15, y: 120 },
|
||||
class: 'light',
|
||||
style: { backgroundColor: 'rgba(255, 0, 255, 0.7)', height: '150px', width: '270px' },
|
||||
parentNode: '4',
|
||||
},
|
||||
{
|
||||
id: '4b1',
|
||||
label: 'Node 4b1',
|
||||
position: { x: 20, y: 40 },
|
||||
class: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
{
|
||||
id: '4b2',
|
||||
label: 'Node 4b2',
|
||||
position: { x: 100, y: 100 },
|
||||
class: 'light',
|
||||
parentNode: '4b',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
@@ -75,21 +74,17 @@ onConnect((params) => addEdges([params]))
|
||||
|
||||
onMounted(() => {
|
||||
// add nodes to parent
|
||||
addNodes(
|
||||
[
|
||||
{
|
||||
id: '999',
|
||||
type: 'input',
|
||||
label: 'Added after mount',
|
||||
position: { x: 20, y: 100 },
|
||||
class: 'light',
|
||||
expandParent: true,
|
||||
},
|
||||
],
|
||||
addNodes([
|
||||
{
|
||||
id: '999',
|
||||
type: 'input',
|
||||
label: 'Added after mount',
|
||||
position: { x: 20, y: 100 },
|
||||
class: 'light',
|
||||
expandParent: true,
|
||||
parentNode: '2',
|
||||
},
|
||||
)
|
||||
])
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -26,11 +26,11 @@ const scale = controlledComputed(
|
||||
() => store.transform[2],
|
||||
)
|
||||
watch(
|
||||
[() => node.value.position, () => node.value.parentNode],
|
||||
[() => node.value.position, () => store.getNode(node.value.parentNode!)],
|
||||
([pos, parent]) => {
|
||||
const xyzPos = {
|
||||
...pos,
|
||||
z: node.value.computedPosition.z,
|
||||
z: node.value.dragging || node.value.selected ? 1000 : node.value.computedPosition.z,
|
||||
}
|
||||
if (parent) {
|
||||
node.value.computedPosition = getXYZPos(parent, xyzPos)
|
||||
@@ -95,7 +95,9 @@ const onDragStop: DraggableEventListener = ({ event, data: { deltaX, deltaY } })
|
||||
|
||||
store.updateNodePosition({ id: node.value.id, diff: { x: 0, y: 0 } })
|
||||
onMounted(() => {
|
||||
useResizeObserver(nodeElement, () => store.updateNodeDimensions([{ id: node.value.id, nodeElement: nodeElement.value, forceUpdate: true }]))
|
||||
useResizeObserver(nodeElement, () =>
|
||||
store.updateNodeDimensions([{ id: node.value.id, nodeElement: nodeElement.value, forceUpdate: true }]),
|
||||
)
|
||||
watch([() => node.value.type, () => node.value.sourcePosition, () => node.value.targetPosition], () =>
|
||||
nextTick(() => store.updateNodeDimensions([{ id: node.value.id, nodeElement: nodeElement.value }])),
|
||||
)
|
||||
@@ -134,7 +136,7 @@ export default {
|
||||
node.class,
|
||||
]"
|
||||
:style="{
|
||||
zIndex: node.dragging || node.selected ? 1000 : node.computedPosition.z,
|
||||
zIndex: node.computedPosition.z,
|
||||
transform: `translate(${node.computedPosition.x}px,${node.computedPosition.y}px)`,
|
||||
pointerEvents: props.selectable || props.draggable ? 'all' : 'none',
|
||||
...node.style,
|
||||
@@ -149,47 +151,47 @@ export default {
|
||||
>
|
||||
<slot
|
||||
v-bind="{
|
||||
nodeElement,
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
data: node.data,
|
||||
selected: !!node.selected,
|
||||
isConnectable: props.connectable,
|
||||
position: node.position,
|
||||
computedPosition: node.computedPosition,
|
||||
dimensions: node.dimensions,
|
||||
isValidTargetPos: node.isValidTargetPos,
|
||||
isValidSourcePos: node.isValidSourcePos,
|
||||
parentNode: node.parentNode ? node.parentNode.id : undefined,
|
||||
dragging: !!node.dragging,
|
||||
zIndex: node.dragging || node.selected ? 1000 : node.computedPosition.z,
|
||||
targetPosition: node.targetPosition,
|
||||
sourcePosition: node.sourcePosition,
|
||||
label: node.label,
|
||||
dragHandle: node.dragHandle,
|
||||
nodeElement,
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
data: node.data,
|
||||
selected: !!node.selected,
|
||||
isConnectable: props.connectable,
|
||||
position: node.position,
|
||||
computedPosition: node.computedPosition,
|
||||
dimensions: node.dimensions,
|
||||
isValidTargetPos: node.isValidTargetPos,
|
||||
isValidSourcePos: node.isValidSourcePos,
|
||||
parentNode: node.parentNode,
|
||||
dragging: !!node.dragging,
|
||||
zIndex: node.dragging || node.selected ? 1000 : node.computedPosition.z,
|
||||
targetPosition: node.targetPosition,
|
||||
sourcePosition: node.sourcePosition,
|
||||
label: node.label,
|
||||
dragHandle: node.dragHandle,
|
||||
}"
|
||||
>
|
||||
<component
|
||||
:is="props.type ?? node.type"
|
||||
v-bind="{
|
||||
nodeElement,
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
data: node.data,
|
||||
selected: !!node.selected,
|
||||
connectable: props.connectable,
|
||||
position: node.position,
|
||||
computedPosition: node.computedPosition,
|
||||
dimensions: node.dimensions,
|
||||
isValidTargetPos: node.isValidTargetPos,
|
||||
isValidSourcePos: node.isValidSourcePos,
|
||||
parentNode: node.parentNode ? node.parentNode.id : undefined,
|
||||
dragging: !!node.dragging,
|
||||
zIndex: node.dragging || node.selected ? 1000 : node.computedPosition.z,
|
||||
targetPosition: node.targetPosition,
|
||||
sourcePosition: node.sourcePosition,
|
||||
label: node.label,
|
||||
dragHandle: node.dragHandle,
|
||||
nodeElement,
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
data: node.data,
|
||||
selected: !!node.selected,
|
||||
connectable: props.connectable,
|
||||
position: node.position,
|
||||
computedPosition: node.computedPosition,
|
||||
dimensions: node.dimensions,
|
||||
isValidTargetPos: node.isValidTargetPos,
|
||||
isValidSourcePos: node.isValidSourcePos,
|
||||
parentNode: node.parentNode,
|
||||
dragging: !!node.dragging,
|
||||
zIndex: node.dragging || node.selected ? 1000 : node.computedPosition.z,
|
||||
targetPosition: node.targetPosition,
|
||||
sourcePosition: node.sourcePosition,
|
||||
label: node.label,
|
||||
dragHandle: node.dragHandle,
|
||||
}"
|
||||
/>
|
||||
</slot>
|
||||
|
||||
+47
-50
@@ -13,6 +13,7 @@ import {
|
||||
Connection,
|
||||
GraphEdge,
|
||||
NodePositionChange,
|
||||
Getters,
|
||||
} from '~/types'
|
||||
import {
|
||||
applyChanges,
|
||||
@@ -34,16 +35,6 @@ import {
|
||||
|
||||
const isDef = <T>(val: T): val is NonNullable<T> => typeof val !== 'undefined'
|
||||
|
||||
const getParent = (root: Node[], id: string): GraphNode | undefined => {
|
||||
let node
|
||||
root.some((n) => {
|
||||
if (n.id === id) return (node = n)
|
||||
if (n.children) return (node = getParent(n.children, id))
|
||||
return false
|
||||
})
|
||||
return node
|
||||
}
|
||||
|
||||
const addEdge = (edgeParams: Edge | Connection, edges: Edge[]) => {
|
||||
if (!edgeParams.source || !edgeParams.target) {
|
||||
console.warn("Can't create edge. An edge needs a source and a target.")
|
||||
@@ -92,25 +83,41 @@ const updateEdgeAction = (edge: GraphEdge, newConnection: Connection, edges: Gra
|
||||
return true
|
||||
}
|
||||
|
||||
const applyEdgeChangesAction = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges)
|
||||
const applyNodeChangesAction = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes)
|
||||
const applyEdgeChangesAction = (changes: EdgeChange[], edges: GraphEdge[], getNode: Getters['getNode']) =>
|
||||
applyChanges(changes, edges, getNode)
|
||||
const applyNodeChangesAction = (changes: NodeChange[], nodes: GraphNode[], getNode: Getters['getNode']) =>
|
||||
applyChanges(changes, nodes, getNode)
|
||||
|
||||
export const parseChildren = (
|
||||
n: Node,
|
||||
p: GraphNode | undefined,
|
||||
arr: GraphNode[],
|
||||
extent: CoordinateExtent,
|
||||
getNode: (id: string) => GraphNode | undefined,
|
||||
) => {
|
||||
const parent = typeof p === 'undefined' || typeof p !== 'object' ? getParent(arr, n.id) : p
|
||||
const parsed = parseNode(n, extent, {
|
||||
...getNode(n.id),
|
||||
parentNode: parent,
|
||||
const createGraphNodes = (nodes: Node[], getNode: Getters['getNode'], currGraphNodes: GraphNode[], extent: CoordinateExtent) => {
|
||||
const parentNodes: Record<string, true> = {}
|
||||
|
||||
const graphNodes = nodes.map((node) => {
|
||||
const parsed = parseNode(node, extent, {
|
||||
...getNode(node.id),
|
||||
parentNode: node.parentNode,
|
||||
})
|
||||
if (node.parentNode) {
|
||||
parentNodes[node.parentNode] = true
|
||||
}
|
||||
|
||||
return parsed
|
||||
})
|
||||
arr.push(parsed)
|
||||
if (n.children && n.children.length) {
|
||||
n.children.forEach((c) => parseChildren(c, parsed, arr, extent, getNode))
|
||||
}
|
||||
|
||||
graphNodes.forEach((node) => {
|
||||
if (node.parentNode && ![...graphNodes, ...currGraphNodes].find((n) => n.id === node.parentNode)) {
|
||||
throw new Error(`Parent node ${node.parentNode} not found`)
|
||||
}
|
||||
|
||||
if (node.parentNode || parentNodes[node.id]) {
|
||||
if (parentNodes[node.id]) {
|
||||
node.isParent = true
|
||||
}
|
||||
const parent = node.parentNode ? getNode(node.parentNode) : undefined
|
||||
if (parent) parent.isParent = true
|
||||
}
|
||||
})
|
||||
|
||||
return graphNodes
|
||||
}
|
||||
|
||||
export default (state: State, getters: ComputedGetters): Actions => {
|
||||
@@ -120,12 +127,12 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
state.nodes.forEach((node) => {
|
||||
if (node.selected) {
|
||||
if (!node.parentNode) {
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }))
|
||||
} else if (!isParentSelected(node)) {
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }))
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }, getters.getNode.value))
|
||||
} else if (!isParentSelected(node, getters.getNode.value)) {
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }, getters.getNode.value))
|
||||
}
|
||||
} else if (node.id === id) {
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }))
|
||||
changes.push(createPositionChange({ node, diff, nodeExtent: state.nodeExtent, dragging }, getters.getNode.value))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -166,7 +173,7 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
|
||||
let changedNodes: NodeChange[]
|
||||
if (state.multiSelectionActive) changedNodes = selectedNodesIds.map((nodeId) => createSelectionChange(nodeId, true))
|
||||
else changedNodes = getSelectionChanges(state.nodes, selectedNodesIds)
|
||||
else changedNodes = getSelectionChanges(state.nodes, selectedNodesIds, getters.getNode.value)
|
||||
|
||||
if (changedNodes.length) state.hooks.nodesChange.trigger(changedNodes)
|
||||
}
|
||||
@@ -175,7 +182,7 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
|
||||
let changedEdges: EdgeChange[]
|
||||
if (state.multiSelectionActive) changedEdges = selectedEdgesIds.map((nodeId) => createSelectionChange(nodeId, true))
|
||||
else changedEdges = getSelectionChanges(state.edges, selectedEdgesIds)
|
||||
else changedEdges = getSelectionChanges(state.edges, selectedEdgesIds, getters.getNode.value)
|
||||
|
||||
if (changedEdges.length) state.hooks.edgesChange.trigger(changedEdges)
|
||||
}
|
||||
@@ -207,12 +214,7 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
|
||||
const setNodes: Actions['setNodes'] = (nodes, extent?: CoordinateExtent) => {
|
||||
if (!state.initialized && !nodes.length) return
|
||||
nodes = nodes.flatMap((node) => {
|
||||
const children: GraphNode[] = []
|
||||
parseChildren(node, undefined, children, extent ?? state.nodeExtent, getters.getNode.value)
|
||||
return children
|
||||
})
|
||||
state.nodes = <GraphNode[]>nodes
|
||||
state.nodes = createGraphNodes(nodes, getters.getNode.value, state.nodes, extent ?? state.nodeExtent)
|
||||
}
|
||||
const setEdges: Actions['setEdges'] = (edges) => {
|
||||
if (!state.initialized && !edges.length) return
|
||||
@@ -241,15 +243,8 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
setEdges(elements.filter(isEdge))
|
||||
}
|
||||
|
||||
const addNodes: Actions['addNodes'] = (nodes, options) => {
|
||||
const parsed = nodes.flatMap((node) => {
|
||||
const children: GraphNode[] = []
|
||||
const parent =
|
||||
options && (typeof options.parentNode === 'string' ? getters.getNode.value(options.parentNode) : options.parentNode)
|
||||
parseChildren(node, parent, children, options?.extent ?? state.nodeExtent, getters.getNode.value)
|
||||
return children
|
||||
})
|
||||
state.nodes.push(...parsed)
|
||||
const addNodes: Actions['addNodes'] = (nodes, extent) => {
|
||||
state.nodes.push(...createGraphNodes(nodes, getters.getNode.value, state.nodes, extent ?? state.nodeExtent))
|
||||
}
|
||||
|
||||
const addEdges: Actions['addEdges'] = (params) => {
|
||||
@@ -275,8 +270,10 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
|
||||
const updateEdge: Actions['updateEdge'] = (oldEdge, newConnection) =>
|
||||
updateEdgeAction(oldEdge, newConnection, state.edges, addEdges)
|
||||
const applyNodeChanges: Actions['applyNodeChanges'] = (changes) => applyNodeChangesAction(changes, state.nodes)
|
||||
const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) => applyEdgeChangesAction(changes, state.edges)
|
||||
const applyNodeChanges: Actions['applyNodeChanges'] = (changes) =>
|
||||
applyNodeChangesAction(changes, state.nodes, getters.getNode.value)
|
||||
const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) =>
|
||||
applyEdgeChangesAction(changes, state.edges, getters.getNode.value)
|
||||
|
||||
const setState: Actions['setState'] = (opts) => {
|
||||
const skip = ['modelValue', 'nodes', 'edges', 'maxZoom', 'minZoom', 'translateExtent']
|
||||
|
||||
+1
-2
@@ -23,7 +23,7 @@ export interface Node<T = any> extends Element<T> {
|
||||
isValidSourcePos?: ValidConnectionFunc
|
||||
extent?: 'parent' | CoordinateExtent
|
||||
expandParent?: boolean
|
||||
children?: Node<T>[]
|
||||
parentNode?: string
|
||||
}
|
||||
|
||||
export interface GraphNode<T = any> extends Node<T> {
|
||||
@@ -33,7 +33,6 @@ export interface GraphNode<T = any> extends Node<T> {
|
||||
isParent: boolean
|
||||
selected: boolean
|
||||
dragging: boolean
|
||||
parentNode?: GraphNode<T>
|
||||
}
|
||||
|
||||
export interface NodeProps<T = any> {
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ export interface Actions<N = any, E = N> {
|
||||
setElements: (elements: Elements<N, E>, extent?: CoordinateExtent) => void
|
||||
setNodes: (nodes: Node<N>[], extent?: CoordinateExtent) => void
|
||||
setEdges: (edges: Edge<E>[]) => void
|
||||
addNodes: <NA = N>(nodes: Node<NA>[], options?: { extent?: CoordinateExtent; parentNode: GraphNode | string }) => void
|
||||
addNodes: <NA = N>(nodes: Node<NA>[], extent?: CoordinateExtent) => void
|
||||
addEdges: <EA = E>(edgesOrConnections: (Edge<EA> | Connection)[]) => void
|
||||
updateEdge: <EU = E>(oldEdge: GraphEdge<EU>, newConnection: Connection) => boolean
|
||||
applyEdgeChanges: <ED = E>(changes: EdgeChange[]) => GraphEdge<ED>[]
|
||||
|
||||
+27
-19
@@ -10,10 +10,11 @@ import {
|
||||
NodeChange,
|
||||
NodeSelectionChange,
|
||||
NodePositionChange,
|
||||
Getters,
|
||||
} from '~/types'
|
||||
|
||||
function handleParentExpand(updateItem: GraphNode) {
|
||||
const parent = updateItem.parentNode
|
||||
function handleParentExpand(updateItem: GraphNode, getNode: Getters['getNode']) {
|
||||
const parent = updateItem.parentNode ? getNode(updateItem.parentNode) : undefined
|
||||
if (parent) {
|
||||
const extendWidth = updateItem.position.x + updateItem.dimensions.width - parent.dimensions.width
|
||||
const extendHeight = updateItem.position.y + updateItem.dimensions.height - parent.dimensions.height
|
||||
@@ -69,8 +70,12 @@ function handleParentExpand(updateItem: GraphNode) {
|
||||
updateItem.position.y = 0
|
||||
}
|
||||
|
||||
parent.dimensions.width = <number>parent.style.width
|
||||
parent.dimensions.height = <number>parent.style.height
|
||||
parent.dimensions.width = (
|
||||
typeof parent.style.width === 'string' ? parseInt((<string>parent.style.width)!, 10) : parent.style.width
|
||||
)!
|
||||
parent.dimensions.height = (
|
||||
typeof parent.style.height === 'string' ? parseInt((<string>parent.style.height)!, 10) : parent.style.height
|
||||
)!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +86,7 @@ export const applyChanges = <
|
||||
>(
|
||||
changes: C[],
|
||||
elements: T[],
|
||||
getNode: Getters['getNode'],
|
||||
): T[] => {
|
||||
let elementIds = elements.map((el) => el.id)
|
||||
changes.forEach((change) => {
|
||||
@@ -95,13 +101,13 @@ export const applyChanges = <
|
||||
if (isGraphNode(el)) {
|
||||
if (typeof change.position !== 'undefined') el.position = change.position
|
||||
if (typeof change.dragging !== 'undefined') el.dragging = change.dragging
|
||||
if (el.expandParent && el.parentNode) handleParentExpand(el)
|
||||
if (el.expandParent && el.parentNode) handleParentExpand(el, getNode)
|
||||
}
|
||||
break
|
||||
case 'dimensions':
|
||||
if (isGraphNode(el)) {
|
||||
if (typeof change.dimensions !== 'undefined') el.dimensions = change.dimensions
|
||||
if (el.expandParent && el.parentNode) handleParentExpand(el)
|
||||
if (el.expandParent && el.parentNode) handleParentExpand(el, getNode)
|
||||
}
|
||||
break
|
||||
case 'remove':
|
||||
@@ -120,7 +126,11 @@ export const createSelectionChange = (id: string, selected: boolean): NodeSelect
|
||||
selected,
|
||||
})
|
||||
|
||||
export const createPositionChange = ({ node, diff, dragging, nodeExtent }: CreatePositionChangeParams): NodePositionChange => {
|
||||
export const createPositionChange = (
|
||||
{ node, diff, dragging, nodeExtent }: CreatePositionChangeParams,
|
||||
getNode: Getters['getNode'],
|
||||
): NodePositionChange => {
|
||||
const parent = node.parentNode ? getNode(node.parentNode) : undefined
|
||||
const change: NodePositionChange = {
|
||||
id: node.id,
|
||||
type: 'position',
|
||||
@@ -131,15 +141,12 @@ export const createPositionChange = ({ node, diff, dragging, nodeExtent }: Creat
|
||||
const nextPosition = { x: node.position.x + diff.x, y: node.position.y + diff.y }
|
||||
let currentExtent = nodeExtent || node.extent
|
||||
|
||||
if (node.extent === 'parent' && node.parentNode && node.dimensions.width && node.dimensions.height) {
|
||||
if (node.extent === 'parent' && parent && node.dimensions.width && node.dimensions.height) {
|
||||
currentExtent =
|
||||
node.parentNode?.dimensions.width && node.parentNode?.dimensions.height
|
||||
parent.dimensions.width && parent.dimensions.height
|
||||
? [
|
||||
[0, 0],
|
||||
[
|
||||
node.parentNode.dimensions.width - node.dimensions.width,
|
||||
node.parentNode.dimensions.height - node.dimensions.height,
|
||||
],
|
||||
[parent.dimensions.width - node.dimensions.width, parent.dimensions.height - node.dimensions.height],
|
||||
]
|
||||
: currentExtent
|
||||
}
|
||||
@@ -150,16 +157,17 @@ export const createPositionChange = ({ node, diff, dragging, nodeExtent }: Creat
|
||||
return change
|
||||
}
|
||||
|
||||
const isParentSelected = (node: GraphNode, selectedIds: string[]): boolean => {
|
||||
if (!node.parentNode) return false
|
||||
if (selectedIds.includes(node.parentNode.id)) return true
|
||||
return isParentSelected(node.parentNode, selectedIds)
|
||||
const isParentSelected = (node: GraphNode, selectedIds: string[], getNode: Getters['getNode']): boolean => {
|
||||
const parent = node.parentNode ? getNode(node.parentNode) : undefined
|
||||
if (!node.parentNode || !parent) return false
|
||||
if (selectedIds.includes(node.parentNode)) return true
|
||||
return isParentSelected(parent, selectedIds, getNode)
|
||||
}
|
||||
|
||||
export const getSelectionChanges = (items: FlowElements, selectedIds: string[]) => {
|
||||
export const getSelectionChanges = (items: FlowElements, selectedIds: string[], getNode: Getters['getNode']) => {
|
||||
return items.reduce((res, item) => {
|
||||
const willBeSelected =
|
||||
selectedIds.includes(item.id) || !!(isGraphNode(item) && item.parentNode && isParentSelected(item, selectedIds))
|
||||
selectedIds.includes(item.id) || !!(isGraphNode(item) && item.parentNode && isParentSelected(item, selectedIds, getNode))
|
||||
|
||||
if (!item.selected && willBeSelected) {
|
||||
res.push(createSelectionChange(item.id, true))
|
||||
|
||||
+7
-6
@@ -16,8 +16,8 @@ import {
|
||||
Rect,
|
||||
Transform,
|
||||
XYPosition,
|
||||
XYZPosition,
|
||||
} from '~/types'
|
||||
XYZPosition, Getters
|
||||
} from "~/types";
|
||||
import { useWindow } from '~/composables'
|
||||
|
||||
const isHTMLElement = (el: EventTarget): el is HTMLElement => ('nodeName' || 'hasAttribute') in el
|
||||
@@ -75,7 +75,6 @@ export const parseNode = (node: Node, nodeExtent: CoordinateExtent, defaults?: P
|
||||
z: typeof node.style?.zIndex === 'string' ? parseInt(node.style?.zIndex as string) : node.style?.zIndex ?? 0,
|
||||
...clampPosition(node.position, nodeExtent),
|
||||
},
|
||||
isParent: !!(node.children && node.children.length),
|
||||
dragging: false,
|
||||
draggable: undefined,
|
||||
selectable: undefined,
|
||||
@@ -335,10 +334,12 @@ export const getXYZPos = (parentNode: GraphNode, computedPosition: XYZPosition):
|
||||
}
|
||||
}
|
||||
|
||||
export const isParentSelected = (node: GraphNode): boolean => {
|
||||
export const isParentSelected = (node: GraphNode, getNode: Getters['getNode']): boolean => {
|
||||
if (!node.parentNode) return false
|
||||
if (node.parentNode.selected) return true
|
||||
return isParentSelected(node.parentNode)
|
||||
const parent = getNode(node.parentNode)
|
||||
if (!parent) return false
|
||||
if (parent.selected) return true
|
||||
return isParentSelected(parent, getNode)
|
||||
}
|
||||
|
||||
export const getMarkerId = (marker: EdgeMarkerType | undefined): string => {
|
||||
|
||||
Reference in New Issue
Block a user