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