108 lines
2.9 KiB
JavaScript
108 lines
2.9 KiB
JavaScript
import { getConnectedEdges, useVueFlow } from '@vue-flow/core'
|
|
import { nextTick, ref } from 'vue'
|
|
|
|
/**
|
|
* Utility composable for specifying animations
|
|
*
|
|
* Animations that resize a node need to call the `updateNodeDimensions` function from store to update node handle positions
|
|
* Otherwise edges do not connect properly
|
|
*/
|
|
export function useTeleport(id) {
|
|
const animation = ref('fade')
|
|
const transition = ref(false)
|
|
const teleport = ref(null)
|
|
|
|
const { updateNodeInternals, findNode, edges } = useVueFlow()
|
|
|
|
/**
|
|
* specify a selector to teleport to
|
|
*
|
|
* teleported elements still behave like they're at their position before,
|
|
* i.e. if they emit events, they will still emit them up their regular tree
|
|
*/
|
|
const fade = (destination, onFinish) => {
|
|
setTimeout(() => {
|
|
// teleport to destination or disable teleport
|
|
teleport.value = destination
|
|
|
|
setTimeout(() => {
|
|
transition.value = false
|
|
|
|
// if destination is null, defer hiding edges until node is teleported back
|
|
if (!destination) {
|
|
onFinish()
|
|
}
|
|
}, 500)
|
|
}, 500)
|
|
}
|
|
|
|
const shrink = (destination, onFinish) => {
|
|
setTimeout(() => {
|
|
// teleport to destination or disable teleport
|
|
teleport.value = destination
|
|
|
|
setTimeout(() => {
|
|
transition.value = false
|
|
|
|
setTimeout(() => {
|
|
// if destination is null, defer hiding edges until node is teleported back
|
|
if (!destination) {
|
|
updateNodeInternals([id])
|
|
|
|
nextTick(() => {
|
|
onFinish()
|
|
})
|
|
}
|
|
}, 500)
|
|
}, 500)
|
|
}, 500)
|
|
}
|
|
|
|
/**
|
|
* specify a selector to teleport to
|
|
*
|
|
* teleported elements still behave like they're at their position before,
|
|
* i.e. if they emit events, they will still emit them up their regular tree
|
|
*/
|
|
const onClick = (destination) => {
|
|
const node = findNode(id)
|
|
|
|
transition.value = true
|
|
|
|
// save current teleport destination to data of node
|
|
node.data.destination = destination
|
|
|
|
// hide connected edges when teleporting
|
|
const connectedEdges = getConnectedEdges([node], edges.value)
|
|
|
|
// if destination is not null, hide edges immediately
|
|
// check if nodes connected to edge are teleported and hide edge if one of them is
|
|
if (destination) {
|
|
connectedEdges.forEach(
|
|
(edge) => (edge.hidden = !!findNode(edge.source).data.destination || !!findNode(edge.target).data.destination),
|
|
)
|
|
}
|
|
|
|
const onFinish = () => {
|
|
connectedEdges.forEach(
|
|
(edge) => (edge.hidden = !!findNode(edge.source).data.destination || !!findNode(edge.target).data.destination),
|
|
)
|
|
}
|
|
|
|
switch (animation.value) {
|
|
case 'fade':
|
|
fade(destination, onFinish)
|
|
break
|
|
case 'shrink':
|
|
shrink(destination, onFinish)
|
|
}
|
|
}
|
|
|
|
return {
|
|
animation,
|
|
transition,
|
|
teleport,
|
|
onClick,
|
|
}
|
|
}
|