refactor(options)!: remove worker and store option
* either unnecessary, broken or needs more work Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,7 @@ interface CustomEdgeProps<T = any> extends EdgeProps<T> {
|
||||
const props = defineProps<CustomEdgeProps>()
|
||||
const store = useVueFlow()
|
||||
const onEdgeClick = (evt: Event, id: string) => {
|
||||
const edge = store.edges.find((edge) => edge.id === id)
|
||||
const edge = store.getEdges.find((edge) => edge.id === id)
|
||||
if (edge) {
|
||||
store.hooks.elementsRemove.trigger([edge])
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ const updateElements = () => {
|
||||
<template>
|
||||
<VueFlow
|
||||
v-model="elements"
|
||||
:worker="true"
|
||||
:loading="{ label: 'Loading...', transition: { name: 'fade', mode: 'out-in' } }"
|
||||
@load="onLoad"
|
||||
@elementsRemove="onElementsRemove"
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
NodeExtent,
|
||||
NodeTypes,
|
||||
EdgeTypes,
|
||||
FlowStore,
|
||||
FlowState,
|
||||
FlowInstance,
|
||||
Loading,
|
||||
@@ -24,11 +23,9 @@ import EdgeRenderer from '../EdgeRenderer/EdgeRenderer.vue'
|
||||
import LoadingIndicator from '../../components/Loading/LoadingIndicator.vue'
|
||||
import { createHooks, initFlow, useWindow, useZoomPanHelper } from '../../composables'
|
||||
import { onLoadGetElements, onLoadProject, onLoadToObject } from '../../utils'
|
||||
import microDiff from 'microdiff'
|
||||
|
||||
interface FlowProps extends FlowOptions {
|
||||
id?: string
|
||||
store?: FlowStore
|
||||
modelValue?: Elements
|
||||
nodeTypes?: NodeTypes
|
||||
edgeTypes?: EdgeTypes
|
||||
@@ -65,10 +62,9 @@ interface FlowProps extends FlowOptions {
|
||||
edgeUpdaterRadius?: number
|
||||
storageKey?: string
|
||||
loading?: Loading
|
||||
worker?: boolean
|
||||
}
|
||||
|
||||
const emit = defineEmits([...Object.keys(createHooks()), 'update:elements', 'update:modelValue'])
|
||||
const emit = defineEmits([...Object.keys(createHooks()), 'update:modelValue'])
|
||||
|
||||
const props = withDefaults(defineProps<FlowProps>(), {
|
||||
modelValue: () => [],
|
||||
@@ -110,7 +106,7 @@ const props = withDefaults(defineProps<FlowProps>(), {
|
||||
loading: false,
|
||||
worker: false,
|
||||
})
|
||||
const store = initFlow(emit, typeof props.storageKey === 'string' ? props.storageKey : props.id, props.store)
|
||||
const store = initFlow(emit, typeof props.storageKey === 'string' ? props.storageKey : props.id)
|
||||
const elements = useVModel(props, 'modelValue', emit)
|
||||
|
||||
// if there are preloaded elements we overwrite the current elements with the stored ones
|
||||
@@ -139,7 +135,7 @@ onBeforeUnmount(() => store?.$dispose())
|
||||
|
||||
invoke(async () => {
|
||||
init(options)
|
||||
await store.setElements(elements.value)
|
||||
store.setElements(elements.value)
|
||||
store.isReady = true
|
||||
|
||||
// if ssr we can't wait for dimensions, they'll never really exist
|
||||
@@ -167,15 +163,20 @@ invoke(async () => {
|
||||
)
|
||||
})
|
||||
|
||||
watch(props.modelValue, (val) => {
|
||||
const diff = microDiff(val, store.elements, { cyclesFix: false })
|
||||
if (diff.length) store.setElements(val)
|
||||
}, { flush: 'post' })
|
||||
watch(elements, (val) =>{
|
||||
const diff = microDiff(val, store.elements, { cyclesFix: false })
|
||||
if (diff.length) store.setElements(val)
|
||||
}, { flush: 'post' })
|
||||
watch(store.elements, (val) => (elements.value = val), { flush: 'post' })
|
||||
watch(
|
||||
() => props.modelValue.length,
|
||||
() => store.setElements(elements.value),
|
||||
)
|
||||
const { pause, resume } = pausableWatch(elements, store.setElements, { flush: 'post' })
|
||||
watch(
|
||||
() => store.elements,
|
||||
(val) => {
|
||||
pause()
|
||||
elements.value = val
|
||||
nextTick(resume)
|
||||
},
|
||||
{ flush: 'post', deep: true },
|
||||
)
|
||||
|
||||
const transitionName = computed(() => {
|
||||
let name = ''
|
||||
@@ -186,11 +187,6 @@ const transitionName = computed(() => {
|
||||
return name
|
||||
})
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'VueFlow'
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="vue-flow">
|
||||
<Transition :key="`vue-flow-transition-${store.$id}`" :name="transitionName">
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
import microDiff from 'microdiff'
|
||||
import { setActivePinia, createPinia, defineStore, StoreDefinition, acceptHMRUpdate } from 'pinia'
|
||||
import { FlowState, FlowActions, Elements, FlowGetters, GraphNode, NextElements, GraphEdge } from '~/types'
|
||||
import { FlowState, FlowActions, Elements, FlowGetters, GraphNode, GraphEdge, Edge } from '~/types'
|
||||
import {
|
||||
clampPosition,
|
||||
getConnectedEdges,
|
||||
getNodesInside,
|
||||
getRectOfNodes,
|
||||
parseElements,
|
||||
defaultNodeTypes,
|
||||
defaultEdgeTypes,
|
||||
deepUnref,
|
||||
isGraphNode,
|
||||
getSourceTargetNodes,
|
||||
isEdge,
|
||||
isGraphEdge,
|
||||
} from '~/utils'
|
||||
import parseElementsWorker from '~/workers/parseElements'
|
||||
|
||||
const pinia = createPinia()
|
||||
|
||||
@@ -43,31 +39,31 @@ export default (id: string, preloadedState: FlowState) => {
|
||||
return nodeTypes
|
||||
},
|
||||
getNodes(): GraphNode[] {
|
||||
const nodes = this.elements.filter(isGraphNode)
|
||||
const n = this.onlyRenderVisibleElements
|
||||
? nodes &&
|
||||
getNodesInside(
|
||||
nodes,
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.dimensions.width,
|
||||
height: this.dimensions.height,
|
||||
},
|
||||
this.transform,
|
||||
true,
|
||||
)
|
||||
: nodes
|
||||
|
||||
return n.filter((node) => !node.isHidden) ?? []
|
||||
if (this.isReady) {
|
||||
const nodes = this.elements.filter((n) => isGraphNode(n) && !n.isHidden) as GraphNode[]
|
||||
return this.onlyRenderVisibleElements
|
||||
? nodes &&
|
||||
getNodesInside(
|
||||
nodes,
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.dimensions.width,
|
||||
height: this.dimensions.height,
|
||||
},
|
||||
this.transform,
|
||||
true,
|
||||
)
|
||||
: nodes ?? []
|
||||
}
|
||||
return []
|
||||
},
|
||||
getEdges(): GraphEdge[] {
|
||||
const edges = this.elements.filter(isEdge)
|
||||
return (
|
||||
edges
|
||||
.filter((edge) => !edge.isHidden)
|
||||
.map((edge) => {
|
||||
if (!isGraphEdge(edge)) {
|
||||
const edges = this.elements.filter((e) => isEdge(e) && !e.isHidden) as Edge[]
|
||||
if (this.isReady) {
|
||||
return (
|
||||
edges
|
||||
.map((edge) => {
|
||||
const { sourceNode, targetNode } = getSourceTargetNodes(edge, this.getNodes)
|
||||
if (!sourceNode) console.warn(`couldn't create edge for source id: ${edge.source}; edge id: ${edge.id}`)
|
||||
if (!targetNode) console.warn(`couldn't create edge for target id: ${edge.target}; edge id: ${edge.id}`)
|
||||
@@ -79,43 +75,19 @@ export default (id: string, preloadedState: FlowState) => {
|
||||
targetNode,
|
||||
},
|
||||
}
|
||||
}
|
||||
return edge
|
||||
})
|
||||
.filter(({ sourceTargetNodes: { sourceNode, targetNode } }) => !!(sourceNode && targetNode)) ?? []
|
||||
)
|
||||
})
|
||||
.filter(({ sourceTargetNodes: { sourceNode, targetNode } }) => !!(sourceNode && targetNode)) ?? []
|
||||
)
|
||||
}
|
||||
return []
|
||||
},
|
||||
getSelectedNodes(): GraphNode[] {
|
||||
return this.selectedElements?.filter(isGraphNode) ?? []
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async setElements(elements) {
|
||||
let next: NextElements = {
|
||||
nextEdges: [],
|
||||
nextNodes: [],
|
||||
}
|
||||
if (!this.worker || import.meta.env.SSR || typeof window === 'undefined') {
|
||||
next = await parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)
|
||||
} else if (this.worker) {
|
||||
const { workerFn, workerTerminate } = parseElementsWorker()
|
||||
const res = await workerFn(
|
||||
deepUnref(elements),
|
||||
deepUnref(this.getNodes),
|
||||
deepUnref(this.getEdges),
|
||||
deepUnref(this.nodeExtent),
|
||||
).catch((err) => {
|
||||
console.error(err)
|
||||
workerTerminate('ERROR')
|
||||
})
|
||||
if (res) {
|
||||
workerTerminate('SUCCESS')
|
||||
next = res
|
||||
} else next = await parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)
|
||||
} else {
|
||||
next = await parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)
|
||||
}
|
||||
this.elements = [...next.nextNodes, ...next.nextEdges]
|
||||
setElements(elements) {
|
||||
this.elements = parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)
|
||||
},
|
||||
setUserSelection(mousePos) {
|
||||
this.selectionActive = true
|
||||
@@ -204,8 +176,7 @@ export default (id: string, preloadedState: FlowState) => {
|
||||
this.elementsSelectable = isInteractive
|
||||
},
|
||||
async addElements(elements: Elements) {
|
||||
const { nextNodes, nextEdges } = await parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)
|
||||
this.elements = [...this.elements, ...nextNodes, ...nextEdges]
|
||||
this.elements = [...this.elements, ...parseElements(elements, this.getNodes, this.getEdges, this.nodeExtent)]
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -3,16 +3,11 @@ import { Edge, EdgeTypes } from './edge'
|
||||
import { NodeExtent, GraphNode, NodeTypes, TranslateExtent, Node } from './node'
|
||||
import { ConnectionLineType, ConnectionMode } from './connection'
|
||||
import { KeyCode, PanOnScrollMode } from './zoom'
|
||||
import { FlowStore } from './store'
|
||||
|
||||
export type ElementId = string
|
||||
export type FlowElement<T = any> = GraphNode<T> | Edge<T>
|
||||
export type FlowElements<T = any> = FlowElement<T>[]
|
||||
export type Elements<T = any> = (Node<T> | Edge<T>)[]
|
||||
export type NextElements = {
|
||||
nextNodes: GraphNode[]
|
||||
nextEdges: Edge[]
|
||||
}
|
||||
|
||||
export type Transform = [number, number, number]
|
||||
|
||||
@@ -148,6 +143,4 @@ export interface FlowOptions {
|
||||
edgeUpdaterRadius?: number
|
||||
storageKey?: string
|
||||
loading?: Loading
|
||||
worker?: boolean
|
||||
store?: FlowStore
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
OnConnectStopFunc,
|
||||
SetConnectionId,
|
||||
} from './connection'
|
||||
import { Edge, EdgeComponent, GraphEdge } from './edge'
|
||||
import { EdgeComponent, GraphEdge } from './edge'
|
||||
import { NodeComponent, NodeExtent, GraphNode, TranslateExtent } from './node'
|
||||
import { D3Selection, D3Zoom, D3ZoomHandler, InitD3ZoomPayload } from './zoom'
|
||||
import { FlowHooks } from './hooks'
|
||||
@@ -73,7 +73,7 @@ export interface FlowState extends FlowOptions {
|
||||
}
|
||||
|
||||
export interface FlowActions {
|
||||
setElements: (elements: Elements) => Promise<void>
|
||||
setElements: (elements: Elements) => void
|
||||
setUserSelection: (mousePos: XYPosition) => void
|
||||
updateUserSelection: (mousePos: XYPosition) => void
|
||||
unsetUserSelection: () => void
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
ConnectionMode,
|
||||
Elements,
|
||||
FlowState,
|
||||
NextElements,
|
||||
NodeExtent,
|
||||
GraphNode,
|
||||
PanOnScrollMode,
|
||||
@@ -97,48 +96,43 @@ export const initialState = (): FlowState => ({
|
||||
vueFlowVersion: typeof __VUE_FLOW_VERSION__ !== 'undefined' ? __VUE_FLOW_VERSION__ : '-',
|
||||
})
|
||||
|
||||
export const parseElements = async (elements: Elements, nodes: GraphNode[], edges: Edge[], nodeExtent: NodeExtent) =>
|
||||
new Promise<NextElements>((resolve) => {
|
||||
const { nextEdges, nextNodes }: NextElements = {
|
||||
nextNodes: [],
|
||||
nextEdges: [],
|
||||
}
|
||||
for (const element of elements) {
|
||||
if (isNode(element)) {
|
||||
const storeNode = nodes[nodes.map((x) => x.id).indexOf(element.id)]
|
||||
export const parseElements = (elements: Elements, nodes: GraphNode[], edges: Edge[], nodeExtent: NodeExtent) => {
|
||||
const parsedElements = []
|
||||
for (const element of elements) {
|
||||
if (isNode(element)) {
|
||||
const storeNode = nodes[nodes.map((x) => x.id).indexOf(element.id)]
|
||||
|
||||
if (storeNode) {
|
||||
const updatedNode = {
|
||||
...storeNode,
|
||||
...element,
|
||||
} as GraphNode
|
||||
if (storeNode) {
|
||||
const updatedNode = {
|
||||
...storeNode,
|
||||
...element,
|
||||
} as GraphNode
|
||||
|
||||
if (typeof element.type !== 'undefined' && element.type !== storeNode.type) {
|
||||
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
|
||||
// When the type of a node changes it is possible that the number or positions of handles changes too.
|
||||
updatedNode.__vf.width = 0
|
||||
}
|
||||
|
||||
nextNodes.push(updatedNode)
|
||||
} else {
|
||||
nextNodes.push(parseNode(element, nodeExtent))
|
||||
if (typeof element.type !== 'undefined' && element.type !== storeNode.type) {
|
||||
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
|
||||
// When the type of a node changes it is possible that the number or positions of handles changes too.
|
||||
updatedNode.__vf.width = 0
|
||||
}
|
||||
} else if (isEdge(element)) {
|
||||
const storeEdge = edges[edges.map((x) => x.id).indexOf(element.id)]
|
||||
|
||||
if (storeEdge) {
|
||||
nextEdges.push({
|
||||
...storeEdge,
|
||||
...element,
|
||||
})
|
||||
} else {
|
||||
nextEdges.push(parseEdge(element))
|
||||
}
|
||||
parsedElements.push(updatedNode)
|
||||
} else {
|
||||
parsedElements.push(parseNode(element, nodeExtent))
|
||||
}
|
||||
} else if (isEdge(element)) {
|
||||
const storeEdge = edges[edges.map((x) => x.id).indexOf(element.id)]
|
||||
|
||||
if (storeEdge) {
|
||||
parsedElements.push({
|
||||
...storeEdge,
|
||||
...element,
|
||||
})
|
||||
} else {
|
||||
parsedElements.push(parseEdge(element))
|
||||
}
|
||||
}
|
||||
resolve({ nextEdges, nextNodes })
|
||||
})
|
||||
|
||||
}
|
||||
return parsedElements
|
||||
}
|
||||
const isObject = (val: any) => val !== null && typeof val === 'object'
|
||||
const isArray = Array.isArray
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import { Connection, Edge, Elements, Node, NodeExtent, GraphNode, XYPosition, NextElements, FlowElement } from '~/types'
|
||||
|
||||
export default () =>
|
||||
useWebWorkerFn((elements: Elements, nodes: GraphNode[], edges: Edge[], nodeExtent: NodeExtent): NextElements => {
|
||||
const clamp = (val: number, min = 0, max = 1): number => Math.min(Math.max(val, min), max)
|
||||
|
||||
const clampPosition = (position: XYPosition, extent: NodeExtent): XYPosition => ({
|
||||
x: clamp(position.x, extent[0][0], extent[1][0]),
|
||||
y: clamp(position.y, extent[0][1], extent[1][1]),
|
||||
})
|
||||
|
||||
const parseNode = (node: Node, nodeExtent: NodeExtent): GraphNode =>
|
||||
Object.assign(node as GraphNode, {
|
||||
id: node.id.toString(),
|
||||
type: node.type || 'default',
|
||||
__vf: {
|
||||
position: clampPosition(node.position, nodeExtent),
|
||||
width: 0,
|
||||
height: 0,
|
||||
handleBounds: {},
|
||||
isDragging: false,
|
||||
},
|
||||
})
|
||||
|
||||
const parseEdge = (edge: Edge): Edge =>
|
||||
Object.assign(edge, {
|
||||
source: edge.source.toString(),
|
||||
target: edge.target.toString(),
|
||||
sourceHandle: edge.sourceHandle ? edge.sourceHandle.toString() : null,
|
||||
targetHandle: edge.targetHandle ? edge.targetHandle.toString() : null,
|
||||
id: edge.id.toString(),
|
||||
type: edge.type || 'default',
|
||||
})
|
||||
|
||||
const isEdge = (element: Node | FlowElement | Connection): element is Edge =>
|
||||
'id' in element && 'source' in element && 'target' in element
|
||||
|
||||
const isNode = (element: Node | FlowElement | Connection): element is Node =>
|
||||
'id' in element && !('source' in element) && !('target' in element)
|
||||
|
||||
const nextElements: NextElements = {
|
||||
nextNodes: [],
|
||||
nextEdges: [],
|
||||
}
|
||||
|
||||
for (const element of elements) {
|
||||
if (isNode(element)) {
|
||||
const storeNode = nodes[nodes.map((x) => x.id).indexOf(element.id)]
|
||||
|
||||
if (storeNode) {
|
||||
const updatedNode = Object.assign(storeNode, element)
|
||||
updatedNode.__vf!.position = element.position
|
||||
|
||||
if (typeof element.type !== 'undefined' && element.type !== storeNode.type) {
|
||||
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
|
||||
// When the type of a node changes it is possible that the number or positions of handles changes too.
|
||||
updatedNode.__vf!.width = 0
|
||||
}
|
||||
|
||||
nextElements.nextNodes.push(updatedNode)
|
||||
} else {
|
||||
nextElements.nextNodes.push(parseNode(element, nodeExtent))
|
||||
}
|
||||
} else if (isEdge(element)) {
|
||||
const storeEdge = edges[edges.map((x) => x.id).indexOf(element.id)]
|
||||
|
||||
if (storeEdge) {
|
||||
nextElements.nextEdges.push(Object.assign(storeEdge, element))
|
||||
} else {
|
||||
nextElements.nextEdges.push(parseEdge(element))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nextElements
|
||||
})
|
||||
Reference in New Issue
Block a user