diff --git a/src/composables/index.ts b/src/composables/index.ts index a0bbd21b..4ff5c57e 100644 --- a/src/composables/index.ts +++ b/src/composables/index.ts @@ -3,4 +3,3 @@ export { default as useKeyPress } from './useKeyPress' export { default as useZoomPanHelper } from './useZoomPanHelper' export { default as useWindow } from './useWindow' export { default as useVueFlow } from './useVueFlow' -export * from './useElementsState' diff --git a/src/composables/useElementsState.ts b/src/composables/useElementsState.ts deleted file mode 100644 index 28d9659f..00000000 --- a/src/composables/useElementsState.ts +++ /dev/null @@ -1,124 +0,0 @@ -import useVueFlow from './useVueFlow' -import { - GraphEdge, - NodeChange, - EdgeChange, - UseEdgesStateOptions, - UseEdgesState, - Edge, - Connection, - GraphNode, - UseNodesStateOptions, - UseNodesState, - UseElementsStateOptions, - UseElementsState, -} from '~/types' -import { applyChanges, connectionExists, getEdgeId, isEdge, isGraphEdge, parseEdge } from '~/utils' -import { parseChildren } from '~/store' - -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.") - return false - } - - let edge - if (isEdge(edgeParams)) { - edge = { ...edgeParams } - } else { - edge = { - ...edgeParams, - id: getEdgeId(edgeParams), - } as Edge - } - edge = parseEdge(edge) - if (connectionExists(edge, edges)) return false - return edge -} - -const updateEdge = (edge: GraphEdge, newConnection: Connection, edges: GraphEdge[]) => { - if (!newConnection.source || !newConnection.target) { - console.warn("Can't create new edge. An edge needs a source and a target.") - return false - } - - const foundEdge = edges.find((e) => isGraphEdge(e) && e.id === edge.id) - - if (!foundEdge) { - console.warn(`The old edge with id=${edge.id} does not exist.`) - return false - } - - edge.id = getEdgeId(newConnection) - edge.source = newConnection.source - edge.target = newConnection.target - edge.sourceHandle = newConnection.sourceHandle - edge.targetHandle = newConnection.targetHandle - - return edge -} - -export const applyEdgeChanges = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges) -export const applyNodeChanges = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes) - -export const useEdgesState = ({ edges, options }: UseEdgesStateOptions = {}): UseEdgesState => { - const { store } = useVueFlow(options) - if (edges && edges.length) store.setEdges(edges) - return { - edges: store.edges, - applyEdgeChanges: (changes) => applyEdgeChanges(changes, store.edges), - setEdges: store.setEdges, - addEdges: (params) => { - params.forEach((param) => { - const edge = addEdge(param, store.edges) - if (edge) { - const sourceNode = store.getNode(edge.source)! - const targetNode = store.getNode(edge.target)! - if (!sourceNode || typeof sourceNode === 'undefined') - console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`) - if (!targetNode || typeof targetNode === 'undefined') - console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`) - - store.edges.push({ - ...edge, - sourceNode, - targetNode, - }) - } - }) - return store.edges - }, - updateEdge: (oldEdge, newConnection) => updateEdge(oldEdge, newConnection, store.edges), - onEdgesChange: store.hooksOn.onEdgesChange, - } -} - -export const useNodesState = ({ nodes, options }: UseNodesStateOptions = {}): UseNodesState => { - const { store } = useVueFlow(options) - if (nodes && nodes.length) store.setNodes(nodes) - return { - nodes: store.nodes, - applyNodeChanges: (changes) => applyNodeChanges(changes, store.nodes), - setNodes: store.setNodes, - addNodes: (nodes, extent) => { - const parsed = nodes.flatMap((node) => { - const children: GraphNode[] = [] - parseChildren(node, undefined, children, extent ?? store.nodeExtent, store.getNode) - return children - }) - store.nodes.push(...parsed) - return store.nodes - }, - onNodesChange: store.hooksOn.onNodesChange, - } -} - -export const useElementsState = ({ edges, nodes, options }: UseElementsStateOptions = {}): UseElementsState => { - const nodesState = useNodesState({ nodes, options }) - const edgesState = useEdgesState({ edges, options }) - - return { - ...nodesState, - ...edgesState, - } -} diff --git a/src/index.ts b/src/index.ts index 26e54654..2c38b07e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,7 +23,6 @@ export { default as useZoomPanHelper } from './composables/useZoomPanHelper' export { default as useVueFlow } from './composables/useVueFlow' export { default as useHandle } from './composables/useHandle' export { default as useWindow } from './composables/useWindow' -export * from './composables/useElementsState' export * from './additional-components' export * from './types' diff --git a/src/store/actions.ts b/src/store/actions.ts index 30252290..64131545 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -1,7 +1,23 @@ -import { CoordinateExtent, EdgeChange, Actions, Getters, State, GraphNode, Node, NodeChange, NodeDimensionChange } from '~/types' import { + CoordinateExtent, + EdgeChange, + Actions, + Getters, + State, + GraphNode, + Node, + NodeChange, + NodeDimensionChange, + Edge, + Connection, + GraphEdge, +} from '~/types' +import { + applyChanges, + connectionExists, createPositionChange, createSelectionChange, + getEdgeId, getSelectionChanges, isEdge, isGraphEdge, @@ -22,6 +38,51 @@ const getParent = (root: Node[], id: string): GraphNode | undefined => { 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.") + return false + } + + let edge + if (isEdge(edgeParams)) { + edge = { ...edgeParams } + } else { + edge = { + ...edgeParams, + id: getEdgeId(edgeParams), + } as Edge + } + edge = parseEdge(edge) + if (connectionExists(edge, edges)) return false + return edge +} + +const updateEdgeAction = (edge: GraphEdge, newConnection: Connection, edges: GraphEdge[]) => { + if (!newConnection.source || !newConnection.target) { + console.warn("Can't create new edge. An edge needs a source and a target.") + return false + } + + const foundEdge = edges.find((e) => isGraphEdge(e) && e.id === edge.id) + + if (!foundEdge) { + console.warn(`The old edge with id=${edge.id} does not exist.`) + return false + } + + edge.id = getEdgeId(newConnection) + edge.source = newConnection.source + edge.target = newConnection.target + edge.sourceHandle = newConnection.sourceHandle + edge.targetHandle = newConnection.targetHandle + + return edge +} + +export const applyEdgeChangesAction = (changes: EdgeChange[], edges: GraphEdge[]) => applyChanges(changes, edges) +export const applyNodeChangesAction = (changes: NodeChange[], nodes: GraphNode[]) => applyChanges(changes, nodes) + export const parseChildren = ( n: Node, p: GraphNode | undefined, @@ -146,6 +207,39 @@ export default (state: State, getters: Getters): Actions => { setEdges(elements.filter(isEdge)) } + const addNodes: Actions['addNodes'] = (nodes, extent) => { + const parsed = nodes.flatMap((node) => { + const children: GraphNode[] = [] + parseChildren(node, undefined, children, extent ?? state.nodeExtent, getters.getNode.value) + return children + }) + state.nodes.push(...parsed) + } + + const addEdges: Actions['addEdges'] = (params) => { + params.forEach((param) => { + const edge = addEdge(param, state.edges) + if (edge) { + const sourceNode = getters.getNode.value(edge.source)! + const targetNode = getters.getNode.value(edge.target)! + if (!sourceNode || typeof sourceNode === 'undefined') + console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`) + if (!targetNode || typeof targetNode === 'undefined') + console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`) + + state.edges.push({ + ...edge, + sourceNode, + targetNode, + }) + } + }) + } + + const updateEdge: Actions['updateEdge'] = (oldEdge, newConnection) => updateEdgeAction(oldEdge, newConnection, state.edges) + const applyNodeChanges: Actions['applyNodeChanges'] = (changes) => applyNodeChangesAction(changes, state.nodes) + const applyEdgeChanges: Actions['applyEdgeChanges'] = (changes) => applyEdgeChangesAction(changes, state.edges) + const setState: Actions['setState'] = (opts) => { if (typeof opts.modelValue !== 'undefined') setElements(opts.modelValue, opts.nodeExtent ?? state.nodeExtent) if (typeof opts.nodes !== 'undefined') setNodes(opts.nodes, opts.nodeExtent ?? state.nodeExtent) @@ -195,6 +289,11 @@ export default (state: State, getters: Getters): Actions => { setElements, setNodes, setEdges, + addNodes, + addEdges, + updateEdge, + applyEdgeChanges, + applyNodeChanges, addSelectedElements, addSelectedNodes, addSelectedEdges, diff --git a/src/types/flow.ts b/src/types/flow.ts index e0f476c3..656eb0a8 100644 --- a/src/types/flow.ts +++ b/src/types/flow.ts @@ -1,10 +1,10 @@ import { CSSProperties, ToRefs } from 'vue' import { GraphEdge, Edge } from './edge' import { GraphNode, CoordinateExtent, Node } from './node' -import { Connection, ConnectionLineType, ConnectionMode } from './connection' +import { ConnectionLineType, ConnectionMode } from './connection' import { KeyCode, PanOnScrollMode, UseZoomPanHelper } from './zoom' import { Actions, Getters, State, FlowStore } from './store' -import { EdgeChange, FlowHooksOn, NodeChange } from './hooks' +import { FlowHooksOn } from './hooks' export type FlowElement = GraphNode | GraphEdge export type FlowElements = FlowElement[] @@ -123,57 +123,6 @@ export interface FlowProps { export type FlowOptions = FlowProps -export interface UseNodesStateOptions { - nodes?: Node[] - options?: Pick< - FlowOptions, - | 'applyDefault' - | 'snapToGrid' - | 'snapGrid' - | 'nodesConnectable' - | 'nodesDraggable' - | 'elementsSelectable' - | 'selectNodesOnDrag' - | 'defaultPosition' - | 'onlyRenderVisibleElements' - | 'nodeExtent' - | 'edgeUpdaterRadius' - > -} -export interface UseEdgesStateOptions { - edges?: Edge[] - options?: Pick< - FlowOptions, - | 'applyDefault' - | 'connectionMode' - | 'connectionLineType' - | 'connectionLineStyle' - | 'elementsSelectable' - | 'selectNodesOnDrag' - | 'defaultPosition' - | 'onlyRenderVisibleElements' - | 'edgesUpdatable' - > -} -export type UseElementsStateOptions = UseNodesStateOptions & UseEdgesStateOptions - -export type UseNodesState = { - nodes: GraphNode[] - applyNodeChanges: (changes: NodeChange[]) => GraphNode[] - setNodes: Actions['setNodes'] - addNodes: (nodes: Node[], extent?: CoordinateExtent) => GraphNode[] - onNodesChange: FlowHooksOn['onNodesChange'] -} -export type UseEdgesState = { - edges: GraphEdge[] - applyEdgeChanges: (changes: EdgeChange[]) => GraphEdge[] - setEdges: Actions['setEdges'] - addEdges: (params: (Edge | Connection)[]) => GraphEdge[] - updateEdge: (oldEdge: GraphEdge, newConnection: Connection) => GraphEdge | false - onEdgesChange: FlowHooksOn['onEdgesChange'] -} -export type UseElementsState = UseNodesState & UseEdgesState - export type UseVueFlow = { id: string store: FlowStore diff --git a/src/types/store.ts b/src/types/store.ts index 64b0bb6e..104a2933 100644 --- a/src/types/store.ts +++ b/src/types/store.ts @@ -2,11 +2,11 @@ import { ComputedRef, ToRefs } from 'vue' import { UnwrapNestedRefs } from '@vue/reactivity' import { Dimensions, Elements, FlowElements, FlowInstance, FlowOptions, Rect, SnapGrid, Transform, XYPosition } from './flow' import { HandleType, EdgeComponent, NodeComponent } from './components' -import { ConnectionLineType, ConnectionMode, SetConnectionId } from './connection' +import { Connection, ConnectionLineType, ConnectionMode, SetConnectionId } from './connection' import { Edge, GraphEdge } from './edge' import { GraphNode, CoordinateExtent, Node } from './node' import { D3Selection, D3Zoom, D3ZoomHandler, KeyCode, PanOnScrollMode } from './zoom' -import { FlowHooks, FlowHooksOn } from './hooks' +import { EdgeChange, FlowHooks, FlowHooksOn, NodeChange } from './hooks' export interface State extends Omit, 'id' | 'modelValue'> { hooks: FlowHooks @@ -74,6 +74,11 @@ export interface Actions { setElements: (elements: Elements, extent?: CoordinateExtent) => void setNodes: (nodes: Node[], extent?: CoordinateExtent) => void setEdges: (edges: Edge[]) => void + addNodes: (nodes: Node[], extent?: CoordinateExtent) => void + addEdges: (params: (Edge | Connection)[]) => void + updateEdge: (oldEdge: GraphEdge, newConnection: Connection) => GraphEdge | false + applyEdgeChanges: (changes: EdgeChange[]) => GraphEdge[] + applyNodeChanges: (changes: NodeChange[]) => GraphNode[] addSelectedElements: (elements: FlowElements) => void addSelectedEdges: (edges: GraphEdge[]) => void addSelectedNodes: (nodes: GraphNode[]) => void