refactor(nodes,edges): Add node/edge add changes
# What's changed? * Elements are not added directly to state but parsed and emitted through change handler and then inserted to state * Remove add element cb from apply changes * Remove reset change (not implemented)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Connection, Edge, Elements, FlowEvents, FlowInstance, FlowTransform, Node, SnapGrid } from '@braks/vue-flow'
|
||||
import { Background, Controls, MarkerType, MiniMap, VueFlow, addEdge } from '@braks/vue-flow/src/index'
|
||||
import { Background, Controls, MarkerType, MiniMap, VueFlow, addEdge } from '@braks/vue-flow'
|
||||
|
||||
const onNodeDragStart = (e: FlowEvents['nodeDragStart']) => console.log('drag start', e)
|
||||
const onNodeDrag = (e: FlowEvents['nodeDrag']) => console.log('drag', e)
|
||||
|
||||
@@ -18,6 +18,7 @@ import type {
|
||||
import {
|
||||
applyChanges,
|
||||
connectionExists,
|
||||
createAdditionChange,
|
||||
createPositionChange,
|
||||
createSelectionChange,
|
||||
getDimensions,
|
||||
@@ -265,20 +266,17 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
const addNodes: Actions['addNodes'] = (nodes, extent) => {
|
||||
const curr = nodes instanceof Function ? nodes(state.nodes) : nodes
|
||||
|
||||
state.nodes = [...state.nodes, ...createGraphNodes(curr, getters.getNode.value, state.nodes, extent ?? state.nodeExtent)]
|
||||
const graphNodes = createGraphNodes(curr, getters.getNode.value, state.nodes, extent ?? state.nodeExtent)
|
||||
const changes = graphNodes.map(createAdditionChange)
|
||||
|
||||
if (changes.length) state.hooks.nodesChange.trigger(changes)
|
||||
}
|
||||
|
||||
const addEdges: Actions['addEdges'] = (params) => {
|
||||
const curr = params instanceof Function ? params(state.edges) : params
|
||||
|
||||
curr.reduce<GraphEdge[]>((acc, param) => {
|
||||
const edge = addEdge(
|
||||
{
|
||||
...param,
|
||||
...state.defaultEdgeOptions,
|
||||
},
|
||||
state.edges,
|
||||
)
|
||||
const changes = curr.reduce((acc, param) => {
|
||||
const edge = addEdge(param, state.edges)
|
||||
if (edge) {
|
||||
const sourceNode = getters.getNode.value(edge.source)!
|
||||
const targetNode = getters.getNode.value(edge.target)!
|
||||
@@ -289,23 +287,28 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
||||
if (missingTarget) console.warn(`[vueflow]: Couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`)
|
||||
if (missingTarget || missingSource) return acc
|
||||
|
||||
acc.push({
|
||||
...edge,
|
||||
sourceNode,
|
||||
targetNode,
|
||||
})
|
||||
acc.push(
|
||||
createAdditionChange<GraphEdge>({
|
||||
...state.defaultEdgeOptions,
|
||||
...edge,
|
||||
sourceNode,
|
||||
targetNode,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, state.edges)
|
||||
}, [] as EdgeChange[])
|
||||
|
||||
if (changes.length) state.hooks.edgesChange.trigger(changes)
|
||||
}
|
||||
|
||||
const updateEdge: Actions['updateEdge'] = (oldEdge, newConnection) =>
|
||||
updateEdgeAction(oldEdge, newConnection, state.edges, addEdges)
|
||||
|
||||
const applyNodeChanges: Actions['applyNodeChanges'] = (changes) => applyChanges(changes, state.nodes, addNodes)
|
||||
const applyNodeChanges: Actions['applyNodeChanges'] = (changes) => applyChanges(changes, state.nodes)
|
||||
|
||||
const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) => applyChanges(changes, state.edges, addEdges)
|
||||
const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) => applyChanges(changes, state.edges)
|
||||
|
||||
const setState: Actions['setState'] = (options) => {
|
||||
const skip = ['modelValue', 'nodes', 'edges', 'maxZoom', 'minZoom', 'translateExtent']
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Dimensions, ElementData, XYPosition } from './flow'
|
||||
import type { Node, NodeHandleBounds } from './node'
|
||||
import type { Edge } from './edge'
|
||||
import type { GraphNode, NodeHandleBounds } from './node'
|
||||
import type { GraphEdge } from './edge'
|
||||
|
||||
export interface NodeDimensionChange {
|
||||
id: string
|
||||
@@ -28,32 +28,21 @@ export interface NodeRemoveChange {
|
||||
}
|
||||
|
||||
export interface NodeAddChange<Data = ElementData> {
|
||||
item: Node<Data>
|
||||
item: GraphNode<Data>
|
||||
type: 'add'
|
||||
}
|
||||
|
||||
export interface NodeResetChange<Data = ElementData> {
|
||||
item: Node<Data>
|
||||
type: 'reset'
|
||||
}
|
||||
|
||||
export type NodeChange =
|
||||
| NodeDimensionChange
|
||||
| NodePositionChange
|
||||
| NodeSelectionChange
|
||||
| NodeRemoveChange
|
||||
| NodeAddChange
|
||||
| NodeResetChange
|
||||
export type NodeChange = NodeDimensionChange | NodePositionChange | NodeSelectionChange | NodeRemoveChange | NodeAddChange
|
||||
|
||||
export type EdgeSelectionChange = NodeSelectionChange
|
||||
|
||||
export type EdgeRemoveChange = NodeRemoveChange
|
||||
|
||||
export interface EdgeAddChange<Data = ElementData> {
|
||||
item: Edge<Data>
|
||||
item: GraphEdge<Data>
|
||||
type: 'add'
|
||||
}
|
||||
export interface EdgeResetChange<Data = ElementData> {
|
||||
item: Edge<Data>
|
||||
type: 'reset'
|
||||
}
|
||||
export type EdgeChange = EdgeSelectionChange | EdgeRemoveChange | EdgeAddChange | EdgeResetChange
|
||||
|
||||
export type EdgeChange = EdgeSelectionChange | EdgeRemoveChange | EdgeAddChange
|
||||
|
||||
export type ElementChange = NodeChange | EdgeChange
|
||||
|
||||
@@ -14,6 +14,8 @@ import type {
|
||||
NodeChange,
|
||||
NodePositionChange,
|
||||
NodeSelectionChange,
|
||||
NodeAddChange,
|
||||
EdgeAddChange,
|
||||
XYPosition,
|
||||
} from '~/types'
|
||||
|
||||
@@ -24,8 +26,7 @@ interface CreatePositionChangeParams {
|
||||
dragging?: boolean
|
||||
}
|
||||
|
||||
function handleParentExpand(updateItem: GraphNode, curr: GraphNode[]) {
|
||||
const parent = updateItem.parentNode ? curr.find((el) => el.id === updateItem.parentNode) : undefined
|
||||
function handleParentExpand(updateItem: GraphNode, parent: GraphNode) {
|
||||
if (parent) {
|
||||
const extendWidth = updateItem.position.x + updateItem.dimensions.width - parent.dimensions.width
|
||||
const extendHeight = updateItem.position.y + updateItem.dimensions.height - parent.dimensions.height
|
||||
@@ -97,13 +98,12 @@ export const applyChanges = <
|
||||
>(
|
||||
changes: C[],
|
||||
elements: T[],
|
||||
addElement?: (els: T[]) => void,
|
||||
): T[] => {
|
||||
let elementIds = elements.map((el) => el.id)
|
||||
changes.forEach((change) => {
|
||||
if (change.type === 'add') {
|
||||
if (addElement) return addElement([change.item as any])
|
||||
else return elements.push(change.item as any)
|
||||
const item = <T>change.item
|
||||
return elements.push(item)
|
||||
}
|
||||
|
||||
const i = elementIds.indexOf((<any>change).id)
|
||||
@@ -116,13 +116,25 @@ 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, elements as GraphNode[])
|
||||
if (el.expandParent && el.parentNode) {
|
||||
const parent = elements.find((parent) => parent.id === el.parentNode)
|
||||
|
||||
if (parent && isGraphNode(parent)) {
|
||||
handleParentExpand(el, parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'dimensions':
|
||||
if (isGraphNode(el)) {
|
||||
if (typeof change.dimensions !== 'undefined') el.dimensions = change.dimensions
|
||||
if (el.expandParent && el.parentNode) handleParentExpand(el, elements as GraphNode[])
|
||||
if (el.expandParent && el.parentNode) {
|
||||
const parent = elements.find((parent) => parent.id === el.parentNode)
|
||||
|
||||
if (parent && isGraphNode(parent)) {
|
||||
handleParentExpand(el, parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'remove':
|
||||
@@ -162,13 +174,12 @@ export const createPositionChange = (
|
||||
let currentExtent = node.extent === 'parent' || typeof node.extent === 'undefined' ? nodeExtent : node.extent
|
||||
|
||||
if (node.extent === 'parent' && parent && node.dimensions.width && node.dimensions.height) {
|
||||
currentExtent =
|
||||
parent.dimensions.width && parent.dimensions.height
|
||||
? [
|
||||
[0, 0],
|
||||
[parent.dimensions.width - node.dimensions.width, parent.dimensions.height - node.dimensions.height],
|
||||
]
|
||||
: currentExtent
|
||||
if (parent.dimensions.width && parent.dimensions.height) {
|
||||
currentExtent = [
|
||||
[0, 0],
|
||||
[parent.dimensions.width - node.dimensions.width, parent.dimensions.height - node.dimensions.height],
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
change.position = currentExtent ? clampPosition(nextPosition, currentExtent) : nextPosition
|
||||
@@ -177,6 +188,17 @@ export const createPositionChange = (
|
||||
return change
|
||||
}
|
||||
|
||||
export const createAdditionChange = <
|
||||
T extends GraphNode | GraphEdge = GraphNode,
|
||||
C extends NodeAddChange | EdgeAddChange = T extends GraphNode ? NodeAddChange : EdgeAddChange,
|
||||
>(
|
||||
item: T,
|
||||
): C =>
|
||||
<C>{
|
||||
item,
|
||||
type: 'add',
|
||||
}
|
||||
|
||||
const isParentSelected = (node: GraphNode, selectedIds: string[], getNode: Getters['getNode']): boolean => {
|
||||
const parent = node.parentNode ? getNode(node.parentNode) : undefined
|
||||
if (!node.parentNode || !parent) return false
|
||||
|
||||
Reference in New Issue
Block a user