refactor(core): replace array fns
This commit is contained in:
@@ -21,27 +21,28 @@ export function useUpdateNodePositions() {
|
|||||||
const positionDiffX = positionDiff.x * xVelo * factor
|
const positionDiffX = positionDiff.x * xVelo * factor
|
||||||
const positionDiffY = positionDiff.y * yVelo * factor
|
const positionDiffY = positionDiff.y * yVelo * factor
|
||||||
|
|
||||||
const nodeUpdates = getSelectedNodes.value
|
const nodeUpdates: NodeDragItem[] = []
|
||||||
.filter((n) => n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'))
|
for (const node of getSelectedNodes.value) {
|
||||||
.map((n) => {
|
if (node.draggable || (nodesDraggable && typeof node.draggable === 'undefined')) {
|
||||||
const nextPosition = { x: n.computedPosition.x + positionDiffX, y: n.computedPosition.y + positionDiffY }
|
const nextPosition = { x: node.computedPosition.x + positionDiffX, y: node.computedPosition.y + positionDiffY }
|
||||||
|
|
||||||
const { computedPosition } = calcNextPosition(
|
const { computedPosition } = calcNextPosition(
|
||||||
n,
|
node,
|
||||||
nextPosition,
|
nextPosition,
|
||||||
emits.error,
|
emits.error,
|
||||||
nodeExtent.value,
|
nodeExtent.value,
|
||||||
n.parentNode ? findNode(n.parentNode) : undefined,
|
node.parentNode ? findNode(node.parentNode) : undefined,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
nodeUpdates.push({
|
||||||
id: n.id,
|
id: node.id,
|
||||||
position: computedPosition,
|
position: computedPosition,
|
||||||
from: n.position,
|
from: node.position,
|
||||||
distance: { x: positionDiff.x, y: positionDiff.y },
|
distance: { x: positionDiff.x, y: positionDiff.y },
|
||||||
dimensions: n.dimensions,
|
dimensions: node.dimensions,
|
||||||
} as NodeDragItem
|
})
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateNodePositions(nodeUpdates, true, false)
|
updateNodePositions(nodeUpdates, true, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,15 +132,16 @@ export function useViewportHelper(state: State) {
|
|||||||
duration: 0,
|
duration: 0,
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
const nodesToFit: GraphNode[] = state.nodes.filter((node) => {
|
const nodesToFit: GraphNode[] = []
|
||||||
|
for (const node of state.nodes) {
|
||||||
const isVisible = node.dimensions.width && node.dimensions.height && (options?.includeHiddenNodes || !node.hidden)
|
const isVisible = node.dimensions.width && node.dimensions.height && (options?.includeHiddenNodes || !node.hidden)
|
||||||
|
|
||||||
if (options.nodes?.length) {
|
if (isVisible) {
|
||||||
return isVisible && options.nodes.includes(node.id)
|
if (!options.nodes?.length || (options.nodes?.length && options.nodes.includes(node.id))) {
|
||||||
|
nodesToFit.push(node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return isVisible
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!nodesToFit.length) {
|
if (!nodesToFit.length) {
|
||||||
return Promise.resolve(false)
|
return Promise.resolve(false)
|
||||||
|
|||||||
+128
-135
@@ -5,6 +5,8 @@ import { until } from '@vueuse/core'
|
|||||||
import type {
|
import type {
|
||||||
Actions,
|
Actions,
|
||||||
CoordinateExtent,
|
CoordinateExtent,
|
||||||
|
Edge,
|
||||||
|
EdgeAddChange,
|
||||||
EdgeChange,
|
EdgeChange,
|
||||||
EdgeRemoveChange,
|
EdgeRemoveChange,
|
||||||
EdgeSelectionChange,
|
EdgeSelectionChange,
|
||||||
@@ -13,6 +15,7 @@ import type {
|
|||||||
GraphEdge,
|
GraphEdge,
|
||||||
GraphNode,
|
GraphNode,
|
||||||
Node,
|
Node,
|
||||||
|
NodeAddChange,
|
||||||
NodeChange,
|
NodeChange,
|
||||||
NodeDimensionChange,
|
NodeDimensionChange,
|
||||||
NodePositionChange,
|
NodePositionChange,
|
||||||
@@ -23,13 +26,11 @@ import type {
|
|||||||
} from '../types'
|
} from '../types'
|
||||||
import { useViewportHelper } from '../composables'
|
import { useViewportHelper } from '../composables'
|
||||||
import {
|
import {
|
||||||
ErrorCode,
|
|
||||||
VueFlowError,
|
|
||||||
addEdgeToStore,
|
|
||||||
applyChanges,
|
applyChanges,
|
||||||
clamp,
|
clamp,
|
||||||
createAdditionChange,
|
createAdditionChange,
|
||||||
createEdgeRemoveChange,
|
createEdgeRemoveChange,
|
||||||
|
createGraphEdges,
|
||||||
createGraphNodes,
|
createGraphNodes,
|
||||||
createNodeRemoveChange,
|
createNodeRemoveChange,
|
||||||
createSelectionChange,
|
createSelectionChange,
|
||||||
@@ -46,7 +47,6 @@ import {
|
|||||||
isNode,
|
isNode,
|
||||||
isRect,
|
isRect,
|
||||||
nodeToRect,
|
nodeToRect,
|
||||||
parseEdge,
|
|
||||||
updateConnectionLookup,
|
updateConnectionLookup,
|
||||||
updateEdgeAction,
|
updateEdgeAction,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
@@ -192,13 +192,18 @@ export function useActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nodeSelectionHandler = (nodes: GraphNode[], selected: boolean) => {
|
const nodeSelectionHandler = (nodes: GraphNode[], selected: boolean) => {
|
||||||
const nodeIds = nodes.map((n) => n.id)
|
const nodeIds: string[] = []
|
||||||
|
for (const node of nodes) {
|
||||||
|
nodeIds.push(node.id)
|
||||||
|
}
|
||||||
|
|
||||||
let changedNodes: NodeChange[]
|
let changedNodes: NodeChange[] = []
|
||||||
let changedEdges: EdgeChange[] = []
|
let changedEdges: EdgeChange[] = []
|
||||||
|
|
||||||
if (state.multiSelectionActive) {
|
if (state.multiSelectionActive) {
|
||||||
changedNodes = nodeIds.map((nodeId) => createSelectionChange(nodeId, selected))
|
for (const nodeId of nodeIds) {
|
||||||
|
changedNodes.push(createSelectionChange(nodeId, selected))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const selectionChanges = getSelectionChanges([...state.nodes, ...state.edges], nodeIds)
|
const selectionChanges = getSelectionChanges([...state.nodes, ...state.edges], nodeIds)
|
||||||
changedNodes = selectionChanges.changedNodes
|
changedNodes = selectionChanges.changedNodes
|
||||||
@@ -215,13 +220,19 @@ export function useActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const edgeSelectionHandler = (edges: GraphEdge[], selected: boolean) => {
|
const edgeSelectionHandler = (edges: GraphEdge[], selected: boolean) => {
|
||||||
const edgeIds = edges.map((e) => e.id)
|
const edgeIds: string[] = []
|
||||||
|
|
||||||
|
for (const edge of edges) {
|
||||||
|
edgeIds.push(edge.id)
|
||||||
|
}
|
||||||
|
|
||||||
let changedNodes: NodeChange[] = []
|
let changedNodes: NodeChange[] = []
|
||||||
let changedEdges: EdgeChange[]
|
let changedEdges: EdgeChange[] = []
|
||||||
|
|
||||||
if (state.multiSelectionActive) {
|
if (state.multiSelectionActive) {
|
||||||
changedEdges = edgeIds.map((edgeId) => createSelectionChange(edgeId, selected))
|
for (const edgeId of edgeIds) {
|
||||||
|
changedEdges.push(createSelectionChange(edgeId, selected))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const selectionChanges = getSelectionChanges([...state.nodes, ...state.edges], edgeIds)
|
const selectionChanges = getSelectionChanges([...state.nodes, ...state.edges], edgeIds)
|
||||||
changedNodes = selectionChanges.changedNodes
|
changedNodes = selectionChanges.changedNodes
|
||||||
@@ -238,14 +249,27 @@ export function useActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const elementSelectionHandler = (elements: Elements, selected: boolean) => {
|
const elementSelectionHandler = (elements: Elements, selected: boolean) => {
|
||||||
const nodeIds = elements.filter(isNode).map((n) => n.id)
|
const nodeIds: string[] = []
|
||||||
const edgeIds = elements.filter(isEdge).map((e) => e.id)
|
const edgeIds: string[] = []
|
||||||
|
|
||||||
let { changedNodes, changedEdges } = getSelectionChanges([...state.nodes, ...state.edges], [...nodeIds, ...edgeIds])
|
for (const element of elements) {
|
||||||
|
if (isNode(element)) {
|
||||||
|
nodeIds.push(element.id)
|
||||||
|
} else if (isEdge(element)) {
|
||||||
|
edgeIds.push(element.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { changedNodes, changedEdges } = getSelectionChanges([...state.nodes, ...state.edges], [...nodeIds, ...edgeIds])
|
||||||
|
|
||||||
if (state.multiSelectionActive) {
|
if (state.multiSelectionActive) {
|
||||||
changedNodes = nodeIds.map((nodeId) => createSelectionChange(nodeId, selected))
|
for (const nodeId of nodeIds) {
|
||||||
changedEdges = edgeIds.map((edgeId) => createSelectionChange(edgeId, selected))
|
changedNodes.push(createSelectionChange(nodeId, selected))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const edgeId of edgeIds) {
|
||||||
|
changedEdges.push(createSelectionChange(edgeId, selected))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedNodes.length) {
|
if (changedNodes.length) {
|
||||||
@@ -274,9 +298,11 @@ export function useActions(
|
|||||||
return nodeSelectionHandler(nodes, false)
|
return nodeSelectionHandler(nodes, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodeIds = nodes.map((n) => n.id)
|
const changedNodes: NodeSelectionChange[] = []
|
||||||
|
|
||||||
const changedNodes = nodeIds.map((nodeId) => createSelectionChange(nodeId, false))
|
for (const node of nodes) {
|
||||||
|
changedNodes.push(createSelectionChange(node.id, false))
|
||||||
|
}
|
||||||
|
|
||||||
if (changedNodes.length) {
|
if (changedNodes.length) {
|
||||||
state.hooks.nodesChange.trigger(changedNodes)
|
state.hooks.nodesChange.trigger(changedNodes)
|
||||||
@@ -288,9 +314,10 @@ export function useActions(
|
|||||||
return edgeSelectionHandler(edges, false)
|
return edgeSelectionHandler(edges, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const edgeIds = edges.map((e) => e.id)
|
const changedEdges: EdgeSelectionChange[] = []
|
||||||
|
for (const edge of edges) {
|
||||||
const changedEdges = edgeIds.map((edgeId) => createSelectionChange(edgeId, false))
|
changedEdges.push(createSelectionChange(edge.id, false))
|
||||||
|
}
|
||||||
|
|
||||||
if (changedEdges.length) {
|
if (changedEdges.length) {
|
||||||
state.hooks.edgesChange.trigger(changedEdges)
|
state.hooks.edgesChange.trigger(changedEdges)
|
||||||
@@ -369,52 +396,20 @@ export function useActions(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const validEdges = state.isValidConnection
|
const validEdges: GraphEdge[] = createGraphEdges(
|
||||||
? nextEdges.filter((edge) =>
|
nextEdges,
|
||||||
state.isValidConnection!(edge, {
|
state.isValidConnection,
|
||||||
edges: state.edges,
|
findNode,
|
||||||
nodes: state.nodes,
|
findEdge,
|
||||||
sourceNode: findNode(edge.source)!,
|
state.hooks.error.trigger,
|
||||||
targetNode: findNode(edge.target)!,
|
state.defaultEdgeOptions,
|
||||||
}),
|
state.nodes,
|
||||||
)
|
state.edges,
|
||||||
: nextEdges
|
)
|
||||||
|
|
||||||
updateConnectionLookup(state.connectionLookup, validEdges)
|
updateConnectionLookup(state.connectionLookup, validEdges)
|
||||||
|
|
||||||
state.edges = validEdges.reduce<GraphEdge[]>((res, edge) => {
|
state.edges = validEdges
|
||||||
const sourceNode = findNode(edge.source)
|
|
||||||
const targetNode = findNode(edge.target)
|
|
||||||
|
|
||||||
const missingSource = !sourceNode || typeof sourceNode === 'undefined'
|
|
||||||
const missingTarget = !targetNode || typeof targetNode === 'undefined'
|
|
||||||
|
|
||||||
if (missingSource && missingTarget) {
|
|
||||||
state.hooks.error.trigger(new VueFlowError(ErrorCode.EDGE_SOURCE_TARGET_MISSING, edge.id, edge.source, edge.target))
|
|
||||||
} else {
|
|
||||||
if (missingSource) {
|
|
||||||
state.hooks.error.trigger(new VueFlowError(ErrorCode.EDGE_SOURCE_MISSING, edge.id, edge.source))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missingTarget) {
|
|
||||||
state.hooks.error.trigger(new VueFlowError(ErrorCode.EDGE_TARGET_MISSING, edge.id, edge.target))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missingSource || missingTarget) {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingEdge = findEdge(edge.id)
|
|
||||||
|
|
||||||
res.push({
|
|
||||||
...parseEdge(edge, existingEdge, state.defaultEdgeOptions),
|
|
||||||
sourceNode,
|
|
||||||
targetNode,
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}, [])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const setElements: Actions['setElements'] = (elements) => {
|
const setElements: Actions['setElements'] = (elements) => {
|
||||||
@@ -434,7 +429,10 @@ export function useActions(
|
|||||||
|
|
||||||
const graphNodes = createGraphNodes(nextNodes, state.nodes, findNode, state.hooks.error.trigger)
|
const graphNodes = createGraphNodes(nextNodes, state.nodes, findNode, state.hooks.error.trigger)
|
||||||
|
|
||||||
const changes = graphNodes.map(createAdditionChange)
|
const changes: NodeAddChange<any>[] = []
|
||||||
|
for (const node of graphNodes) {
|
||||||
|
changes.push(createAdditionChange(node))
|
||||||
|
}
|
||||||
|
|
||||||
if (changes.length) {
|
if (changes.length) {
|
||||||
state.hooks.nodesChange.trigger(changes)
|
state.hooks.nodesChange.trigger(changes)
|
||||||
@@ -445,35 +443,21 @@ export function useActions(
|
|||||||
let nextEdges = params instanceof Function ? params(state.edges) : params
|
let nextEdges = params instanceof Function ? params(state.edges) : params
|
||||||
nextEdges = Array.isArray(nextEdges) ? nextEdges : [nextEdges]
|
nextEdges = Array.isArray(nextEdges) ? nextEdges : [nextEdges]
|
||||||
|
|
||||||
const validEdges = state.isValidConnection
|
const validEdges = createGraphEdges(
|
||||||
? nextEdges.filter((edge) => {
|
nextEdges,
|
||||||
return state.isValidConnection?.(edge, {
|
state.isValidConnection,
|
||||||
edges: state.edges,
|
findNode,
|
||||||
nodes: state.nodes,
|
findEdge,
|
||||||
sourceNode: findNode(edge.source)!,
|
state.hooks.error.trigger,
|
||||||
targetNode: findNode(edge.target)!,
|
state.defaultEdgeOptions,
|
||||||
})
|
state.nodes,
|
||||||
})
|
state.edges,
|
||||||
: nextEdges
|
)
|
||||||
|
|
||||||
const changes = validEdges.reduce((edgeChanges, connection) => {
|
const changes: EdgeAddChange[] = []
|
||||||
const edge = addEdgeToStore(connection, state.edges, state.hooks.error.trigger, state.defaultEdgeOptions)
|
for (const edge of validEdges) {
|
||||||
|
changes.push(createAdditionChange(edge))
|
||||||
if (edge) {
|
}
|
||||||
const sourceNode = findNode(edge.source)!
|
|
||||||
const targetNode = findNode(edge.target)!
|
|
||||||
|
|
||||||
edgeChanges.push(
|
|
||||||
createAdditionChange<GraphEdge>({
|
|
||||||
...edge,
|
|
||||||
sourceNode,
|
|
||||||
targetNode,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return edgeChanges
|
|
||||||
}, [] as EdgeChange[])
|
|
||||||
|
|
||||||
if (changes.length) {
|
if (changes.length) {
|
||||||
state.hooks.edgesChange.trigger(changes)
|
state.hooks.edgesChange.trigger(changes)
|
||||||
@@ -488,28 +472,27 @@ export function useActions(
|
|||||||
const edgeChanges: EdgeRemoveChange[] = []
|
const edgeChanges: EdgeRemoveChange[] = []
|
||||||
|
|
||||||
function createEdgeRemovalChanges(nodes: Node[]) {
|
function createEdgeRemovalChanges(nodes: Node[]) {
|
||||||
const connections = getConnectedEdges(nodes).filter((edge) => (isDef(edge.deletable) ? edge.deletable : true))
|
const connectedEdges = getConnectedEdges(nodes)
|
||||||
|
for (const edge of connectedEdges) {
|
||||||
edgeChanges.push(
|
if (isDef(edge.deletable) ? edge.deletable : true) {
|
||||||
...connections.map((connection) =>
|
edgeChanges.push(createEdgeRemoveChange(edge.id, edge.source, edge.target, edge.sourceHandle, edge.targetHandle))
|
||||||
createEdgeRemoveChange(
|
}
|
||||||
connection.id,
|
}
|
||||||
connection.source,
|
|
||||||
connection.target,
|
|
||||||
connection.sourceHandle,
|
|
||||||
connection.targetHandle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursively get all children and if the child is a parent, get those children as well until all nodes have been removed that are children of the current node
|
// recursively get all children and if the child is a parent, get those children as well until all nodes have been removed that are children of the current node
|
||||||
function createChildrenRemovalChanges(id: string) {
|
function createChildrenRemovalChanges(id: string) {
|
||||||
const children = state.nodes.filter((n) => n.parentNode === id)
|
const children: GraphNode[] = []
|
||||||
|
for (const node of state.nodes) {
|
||||||
|
if (node.parentNode === id) {
|
||||||
|
children.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (children.length) {
|
if (children.length) {
|
||||||
const childIds = children.map((n) => n.id)
|
for (const child of children) {
|
||||||
nodeChanges.push(...childIds.map((id) => createNodeRemoveChange(id)))
|
nodeChanges.push(createNodeRemoveChange(child.id))
|
||||||
|
}
|
||||||
|
|
||||||
if (removeConnectedEdges) {
|
if (removeConnectedEdges) {
|
||||||
createEdgeRemovalChanges(children)
|
createEdgeRemovalChanges(children)
|
||||||
@@ -684,17 +667,22 @@ export function useActions(
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return (nodes || state.nodes).filter((n) => {
|
const intersections: GraphNode[] = []
|
||||||
|
for (const n of nodes || state.nodes) {
|
||||||
if (!isRect && (n.id === node!.id || !n.computedPosition)) {
|
if (!isRect && (n.id === node!.id || !n.computedPosition)) {
|
||||||
return false
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const currNodeRect = nodeToRect(n)
|
const currNodeRect = nodeToRect(n)
|
||||||
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect)
|
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect)
|
||||||
const partiallyVisible = partially && overlappingArea > 0
|
const partiallyVisible = partially && overlappingArea > 0
|
||||||
|
|
||||||
return partiallyVisible || overlappingArea >= Number(nodeRect.width) * Number(nodeRect.height)
|
if (partiallyVisible || overlappingArea >= Number(nodeRect.width) * Number(nodeRect.height)) {
|
||||||
})
|
intersections.push(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return intersections
|
||||||
}
|
}
|
||||||
|
|
||||||
const isNodeIntersecting: Actions['isNodeIntersecting'] = (nodeOrRect, area, partially = true) => {
|
const isNodeIntersecting: Actions['isNodeIntersecting'] = (nodeOrRect, area, partially = true) => {
|
||||||
@@ -804,32 +792,37 @@ export function useActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toObject: Actions['toObject'] = () => {
|
const toObject: Actions['toObject'] = () => {
|
||||||
|
const nodes: Node[] = []
|
||||||
|
const edges: Edge[] = []
|
||||||
|
|
||||||
|
for (const node of state.nodes) {
|
||||||
|
const {
|
||||||
|
computedPosition: _,
|
||||||
|
handleBounds: __,
|
||||||
|
selected: ___,
|
||||||
|
dimensions: ____,
|
||||||
|
isParent: _____,
|
||||||
|
resizing: ______,
|
||||||
|
dragging: _______,
|
||||||
|
initialized: ________,
|
||||||
|
events: _________,
|
||||||
|
...rest
|
||||||
|
} = node
|
||||||
|
|
||||||
|
nodes.push(rest)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const edge of state.edges) {
|
||||||
|
const { selected: _, sourceNode: __, targetNode: ___, events: ____, ...rest } = edge
|
||||||
|
|
||||||
|
edges.push(rest)
|
||||||
|
}
|
||||||
|
|
||||||
// we have to stringify/parse so objects containing refs (like nodes and edges) can potentially be saved in a storage
|
// we have to stringify/parse so objects containing refs (like nodes and edges) can potentially be saved in a storage
|
||||||
return JSON.parse(
|
return JSON.parse(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
nodes: state.nodes.map((n) => {
|
nodes,
|
||||||
// omit internal properties when exporting
|
edges,
|
||||||
const {
|
|
||||||
computedPosition: _,
|
|
||||||
handleBounds: __,
|
|
||||||
selected: ___,
|
|
||||||
dimensions: ____,
|
|
||||||
isParent: _____,
|
|
||||||
resizing: ______,
|
|
||||||
dragging: _______,
|
|
||||||
initialized: ________,
|
|
||||||
events: _________,
|
|
||||||
...rest
|
|
||||||
} = n
|
|
||||||
|
|
||||||
return rest
|
|
||||||
}),
|
|
||||||
edges: state.edges.map((e) => {
|
|
||||||
// omit internal properties when exporting
|
|
||||||
const { selected: _, sourceNode: __, targetNode: ___, events: ____, ...rest } = e
|
|
||||||
|
|
||||||
return rest
|
|
||||||
}),
|
|
||||||
position: [state.viewport.x, state.viewport.y],
|
position: [state.viewport.x, state.viewport.y],
|
||||||
zoom: state.viewport.zoom,
|
zoom: state.viewport.zoom,
|
||||||
viewport: state.viewport,
|
viewport: state.viewport,
|
||||||
|
|||||||
@@ -58,22 +58,29 @@ export function useGetters(state: State, nodeIds: ComputedRef<string[]>, edgeIds
|
|||||||
})
|
})
|
||||||
|
|
||||||
const getNodes: ComputedGetters['getNodes'] = computed(() => {
|
const getNodes: ComputedGetters['getNodes'] = computed(() => {
|
||||||
const nodes = state.nodes.filter((n) => !n.hidden)
|
const nodes: GraphNode[] = []
|
||||||
|
|
||||||
return state.onlyRenderVisibleElements
|
for (const node of state.nodes) {
|
||||||
? nodes &&
|
if (!node.hidden) {
|
||||||
getNodesInside(
|
nodes.push(node)
|
||||||
nodes,
|
}
|
||||||
{
|
}
|
||||||
x: 0,
|
|
||||||
y: 0,
|
if (state.onlyRenderVisibleElements) {
|
||||||
width: state.dimensions.width,
|
return getNodesInside(
|
||||||
height: state.dimensions.height,
|
nodes,
|
||||||
},
|
{
|
||||||
state.viewport,
|
x: 0,
|
||||||
true,
|
y: 0,
|
||||||
)
|
width: state.dimensions.width,
|
||||||
: nodes ?? []
|
height: state.dimensions.height,
|
||||||
|
},
|
||||||
|
state.viewport,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes
|
||||||
})
|
})
|
||||||
|
|
||||||
const edgeHidden = (e: GraphEdge, source?: GraphNode, target?: GraphNode) => {
|
const edgeHidden = (e: GraphEdge, source?: GraphNode, target?: GraphNode) => {
|
||||||
@@ -89,48 +96,87 @@ export function useGetters(state: State, nodeIds: ComputedRef<string[]>, edgeIds
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getEdges: ComputedGetters['getEdges'] = computed(() => {
|
const getEdges: ComputedGetters['getEdges'] = computed(() => {
|
||||||
if (!state.onlyRenderVisibleElements) {
|
const edges: GraphEdge[] = []
|
||||||
return state.edges.filter((edge) => edgeHidden(edge))
|
|
||||||
|
for (const edge of state.edges) {
|
||||||
|
if (!edgeHidden(edge)) {
|
||||||
|
edges.push(edge)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.edges.filter((e) => {
|
if (state.onlyRenderVisibleElements) {
|
||||||
const source = getNode.value(e.source)!
|
const visibleEdges: GraphEdge[] = []
|
||||||
const target = getNode.value(e.target)!
|
|
||||||
|
|
||||||
return (
|
for (const edge of edges) {
|
||||||
edgeHidden(e, source, target) &&
|
const source = getNode.value(edge.source)!
|
||||||
isEdgeVisible({
|
const target = getNode.value(edge.target)!
|
||||||
sourcePos: source.computedPosition || { x: 0, y: 0 },
|
|
||||||
targetPos: target.computedPosition || { x: 0, y: 0 },
|
if (
|
||||||
sourceWidth: source.dimensions.width,
|
isEdgeVisible({
|
||||||
sourceHeight: source.dimensions.height,
|
sourcePos: source.computedPosition || { x: 0, y: 0 },
|
||||||
targetWidth: target.dimensions.width,
|
targetPos: target.computedPosition || { x: 0, y: 0 },
|
||||||
targetHeight: target.dimensions.height,
|
sourceWidth: source.dimensions.width,
|
||||||
width: state.dimensions.width,
|
sourceHeight: source.dimensions.height,
|
||||||
height: state.dimensions.height,
|
targetWidth: target.dimensions.width,
|
||||||
viewport: state.viewport,
|
targetHeight: target.dimensions.height,
|
||||||
})
|
width: state.dimensions.width,
|
||||||
)
|
height: state.dimensions.height,
|
||||||
})
|
viewport: state.viewport,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
visibleEdges.push(edge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return visibleEdges
|
||||||
|
}
|
||||||
|
|
||||||
|
return edges
|
||||||
})
|
})
|
||||||
|
|
||||||
const getElements: ComputedGetters['getElements'] = computed(() => [...getNodes.value, ...getEdges.value])
|
const getElements: ComputedGetters['getElements'] = computed(() => [...getNodes.value, ...getEdges.value])
|
||||||
|
|
||||||
const getSelectedNodes: ComputedGetters['getSelectedNodes'] = computed(() => state.nodes.filter((n) => n.selected))
|
const getSelectedNodes: ComputedGetters['getSelectedNodes'] = computed(() => {
|
||||||
|
const selectedNodes: GraphNode[] = []
|
||||||
|
for (const node of state.nodes) {
|
||||||
|
if (node.selected) {
|
||||||
|
selectedNodes.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getSelectedEdges: ComputedGetters['getSelectedEdges'] = computed(() => state.edges.filter((e) => e.selected))
|
return selectedNodes
|
||||||
|
})
|
||||||
|
|
||||||
|
const getSelectedEdges: ComputedGetters['getSelectedEdges'] = computed(() => {
|
||||||
|
const selectedEdges: GraphEdge[] = []
|
||||||
|
for (const edge of state.edges) {
|
||||||
|
if (edge.selected) {
|
||||||
|
selectedEdges.push(edge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedEdges
|
||||||
|
})
|
||||||
|
|
||||||
const getSelectedElements: ComputedGetters['getSelectedElements'] = computed(() => [
|
const getSelectedElements: ComputedGetters['getSelectedElements'] = computed(() => [
|
||||||
...(getSelectedNodes.value ?? []),
|
...getSelectedNodes.value,
|
||||||
...(getSelectedEdges.value ?? []),
|
...getSelectedEdges.value,
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in next major version; use `useNodesInitialized` instead
|
* @deprecated will be removed in next major version; use `useNodesInitialized` instead
|
||||||
*/
|
*/
|
||||||
const getNodesInitialized: ComputedGetters['getNodesInitialized'] = computed(() =>
|
const getNodesInitialized: ComputedGetters['getNodesInitialized'] = computed(() => {
|
||||||
getNodes.value.filter((n) => n.initialized && n.handleBounds !== undefined),
|
const initializedNodes: GraphNode[] = []
|
||||||
)
|
|
||||||
|
for (const node of state.nodes) {
|
||||||
|
if (node.initialized && node.handleBounds !== undefined) {
|
||||||
|
initializedNodes.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return initializedNodes
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated will be removed in next major version; use `useNodesInitialized` instead
|
* @deprecated will be removed in next major version; use `useNodesInitialized` instead
|
||||||
|
|||||||
@@ -133,9 +133,11 @@ export function applyChanges<
|
|||||||
const elementIds = elements.map((el) => el.id)
|
const elementIds = elements.map((el) => el.id)
|
||||||
|
|
||||||
for (const element of elements) {
|
for (const element of elements) {
|
||||||
const currentChanges = changes.filter((c) => (<any>c).id === element.id)
|
for (const currentChange of changes) {
|
||||||
|
if ((<any>currentChange).id !== element.id) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for (const currentChange of currentChanges) {
|
|
||||||
switch (currentChange.type) {
|
switch (currentChange.type) {
|
||||||
case 'select':
|
case 'select':
|
||||||
element.selected = currentChange.selected
|
element.selected = currentChange.selected
|
||||||
|
|||||||
@@ -34,28 +34,32 @@ export function getDragItems(
|
|||||||
findNode: Actions['findNode'],
|
findNode: Actions['findNode'],
|
||||||
nodeId?: string,
|
nodeId?: string,
|
||||||
): NodeDragItem[] {
|
): NodeDragItem[] {
|
||||||
return nodes
|
const dragItems: NodeDragItem[] = []
|
||||||
.filter(
|
for (const node of nodes) {
|
||||||
(n) =>
|
if (
|
||||||
(n.selected || n.id === nodeId) &&
|
(node.selected || node.id === nodeId) &&
|
||||||
(!n.parentNode || !isParentSelected(n, findNode)) &&
|
(!node.parentNode || !isParentSelected(node, findNode)) &&
|
||||||
(n.draggable || (nodesDraggable && typeof n.draggable === 'undefined')),
|
(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'))
|
||||||
)
|
) {
|
||||||
.map((n) =>
|
dragItems.push(
|
||||||
markRaw({
|
markRaw({
|
||||||
id: n.id,
|
id: node.id,
|
||||||
position: n.position || { x: 0, y: 0 },
|
position: node.position || { x: 0, y: 0 },
|
||||||
distance: {
|
distance: {
|
||||||
x: mousePos.x - n.computedPosition?.x || 0,
|
x: mousePos.x - node.computedPosition?.x || 0,
|
||||||
y: mousePos.y - n.computedPosition?.y || 0,
|
y: mousePos.y - node.computedPosition?.y || 0,
|
||||||
},
|
},
|
||||||
from: n.computedPosition,
|
from: node.computedPosition,
|
||||||
extent: n.extent,
|
extent: node.extent,
|
||||||
parentNode: n.parentNode,
|
parentNode: node.parentNode,
|
||||||
dimensions: n.dimensions,
|
dimensions: node.dimensions,
|
||||||
expandParent: n.expandParent,
|
expandParent: node.expandParent,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dragItems
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEventHandlerParams({
|
export function getEventHandlerParams({
|
||||||
@@ -67,15 +71,14 @@ export function getEventHandlerParams({
|
|||||||
dragItems: NodeDragItem[]
|
dragItems: NodeDragItem[]
|
||||||
findNode: Actions['findNode']
|
findNode: Actions['findNode']
|
||||||
}): [GraphNode, GraphNode[]] {
|
}): [GraphNode, GraphNode[]] {
|
||||||
const extendedDragItems = dragItems.reduce((acc, dragItem) => {
|
const extendedDragItems: GraphNode[] = []
|
||||||
|
for (const dragItem of dragItems) {
|
||||||
const node = findNode(dragItem.id)
|
const node = findNode(dragItem.id)
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
acc.push(node)
|
extendedDragItems.push(node)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return acc
|
|
||||||
}, [] as GraphNode[])
|
|
||||||
|
|
||||||
return [id ? extendedDragItems.find((n) => n.id === id)! : extendedDragItems[0], extendedDragItems]
|
return [id ? extendedDragItems.find((n) => n.id === id)! : extendedDragItems[0], extendedDragItems]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
import { markRaw, unref } from 'vue'
|
import { markRaw, unref } from 'vue'
|
||||||
import type { Actions, Connection, ConnectionLookup, DefaultEdgeOptions, Edge, GraphEdge, GraphNode, Node, State } from '../types'
|
import type {
|
||||||
|
Actions,
|
||||||
|
Connection,
|
||||||
|
ConnectionLookup,
|
||||||
|
DefaultEdgeOptions,
|
||||||
|
Edge,
|
||||||
|
GraphEdge,
|
||||||
|
GraphNode,
|
||||||
|
Node,
|
||||||
|
State,
|
||||||
|
ValidConnectionFunc,
|
||||||
|
VueFlowStore,
|
||||||
|
} from '../types'
|
||||||
import { ErrorCode, VueFlowError, connectionExists, getEdgeId, isEdge, isNode, parseEdge, parseNode } from '.'
|
import { ErrorCode, VueFlowError, connectionExists, getEdgeId, isEdge, isNode, parseEdge, parseNode } from '.'
|
||||||
|
|
||||||
type NonUndefined<T> = T extends undefined ? never : T
|
type NonUndefined<T> = T extends undefined ? never : T
|
||||||
@@ -195,3 +207,71 @@ export function areConnectionMapsEqual(a?: Map<string, Connection>, b?: Map<stri
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export function createGraphEdges(
|
||||||
|
nextEdges: (Edge | Connection)[],
|
||||||
|
isValidConnection: ValidConnectionFunc | null,
|
||||||
|
findNode: Actions['findNode'],
|
||||||
|
findEdge: Actions['findEdge'],
|
||||||
|
onError: VueFlowStore['emits']['error'],
|
||||||
|
defaultEdgeOptions: DefaultEdgeOptions | undefined,
|
||||||
|
nodes: GraphNode[],
|
||||||
|
edges: GraphEdge[],
|
||||||
|
) {
|
||||||
|
const validEdges: GraphEdge[] = []
|
||||||
|
|
||||||
|
for (const edgeOrConnection of nextEdges) {
|
||||||
|
const edge = isEdge(edgeOrConnection)
|
||||||
|
? edgeOrConnection
|
||||||
|
: addEdgeToStore(edgeOrConnection, edges, onError, defaultEdgeOptions)
|
||||||
|
|
||||||
|
if (!edge) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceNode = findNode(edge.source)
|
||||||
|
const targetNode = findNode(edge.target)
|
||||||
|
|
||||||
|
if (!sourceNode || !targetNode) {
|
||||||
|
onError(new VueFlowError(ErrorCode.EDGE_SOURCE_TARGET_MISSING, edge.id, edge.source, edge.target))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sourceNode) {
|
||||||
|
onError(new VueFlowError(ErrorCode.EDGE_SOURCE_MISSING, edge.id, edge.source))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetNode) {
|
||||||
|
onError(new VueFlowError(ErrorCode.EDGE_TARGET_MISSING, edge.id, edge.target))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isValidConnection) {
|
||||||
|
const isValid = isValidConnection(edge, {
|
||||||
|
edges,
|
||||||
|
nodes,
|
||||||
|
sourceNode,
|
||||||
|
targetNode,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
onError(new VueFlowError(ErrorCode.EDGE_INVALID, edge.id))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingEdge = findEdge(edge.id)
|
||||||
|
|
||||||
|
validEdges.push({
|
||||||
|
...parseEdge(edge, existingEdge, defaultEdgeOptions),
|
||||||
|
sourceNode,
|
||||||
|
targetNode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return validEdges
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user