feat(viewpane): defer viewport functions until pane is ready
# What's changed? * Allow vue flow id to be passed to `useZoomPanHelper` and defer viewport functions until pane is ready * Remove warning for using viewport functions too early
This commit is contained in:
@@ -38,7 +38,7 @@ export class Storage {
|
|||||||
|
|
||||||
const getters = useGetters(reactiveState)
|
const getters = useGetters(reactiveState)
|
||||||
|
|
||||||
const actions = useActions(reactiveState, getters)
|
const actions = useActions(reactiveState, getters, id)
|
||||||
|
|
||||||
const hooksOn = <any>{}
|
const hooksOn = <any>{}
|
||||||
Object.entries(reactiveState.hooks).forEach(([n, h]) => {
|
Object.entries(reactiveState.hooks).forEach(([n, h]) => {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const untilDimensions = async (dimensions: Dimensions, getNodes: Getters['getNod
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (): ViewportFunctions => {
|
export default (vueFlowId?: string): ViewportFunctions => {
|
||||||
const {
|
const {
|
||||||
onPaneReady,
|
onPaneReady,
|
||||||
nodes,
|
nodes,
|
||||||
@@ -42,7 +42,7 @@ export default (): ViewportFunctions => {
|
|||||||
snapToGrid,
|
snapToGrid,
|
||||||
snapGrid,
|
snapGrid,
|
||||||
getNodes,
|
getNodes,
|
||||||
} = $(useVueFlow())
|
} = $(useVueFlow({ id: vueFlowId }))
|
||||||
|
|
||||||
let hasDimensions = $ref(false)
|
let hasDimensions = $ref(false)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import NodeRenderer from '../NodeRenderer/NodeRenderer.vue'
|
import NodeRenderer from '../NodeRenderer/NodeRenderer.vue'
|
||||||
import EdgeRenderer from '../EdgeRenderer/EdgeRenderer.vue'
|
import EdgeRenderer from '../EdgeRenderer/EdgeRenderer.vue'
|
||||||
import { useVueFlow, useWindow, useZoomPanHelper } from '../../composables'
|
import { useVueFlow, useWindow } from '../../composables'
|
||||||
import type { Dimensions } from '../../types'
|
import type { Dimensions } from '../../types'
|
||||||
|
|
||||||
const { id, nodes, edges, viewport, snapToGrid, snapGrid, dimensions, setState, fitViewOnInit, emits } = $(useVueFlow())
|
const { id, nodes, edges, viewport, snapToGrid, snapGrid, dimensions, setState, fitViewOnInit, emits, fitView, ...rest } =
|
||||||
// eslint-disable-next-line prefer-const
|
useVueFlow()
|
||||||
let { fitView, zoomIn, zoomOut, zoomTo, setTransform, setCenter, fitBounds, ...rest } = useVueFlow()
|
|
||||||
|
|
||||||
const untilDimensions = async (dim: Dimensions) => {
|
const untilDimensions = async (dim: Dimensions) => {
|
||||||
// if ssr we can't wait for dimensions, they'll never really exist
|
// if ssr we can't wait for dimensions, they'll never really exist
|
||||||
@@ -23,26 +22,26 @@ let ready = $ref(false)
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// wait until proper dimensions have been established, otherwise fitView will have wrong bounds when called at paneReady
|
// wait until proper dimensions have been established, otherwise fitView will have wrong bounds when called at paneReady
|
||||||
await untilDimensions(dimensions)
|
await untilDimensions(dimensions.value)
|
||||||
|
|
||||||
// create new instance and set to state
|
|
||||||
const zoomPanHelper = useZoomPanHelper()
|
|
||||||
|
|
||||||
fitView = (params = { padding: 0.1 }) => {
|
|
||||||
zoomPanHelper.fitView(params)
|
|
||||||
}
|
|
||||||
zoomIn = zoomPanHelper.zoomIn
|
|
||||||
zoomOut = zoomPanHelper.zoomOut
|
|
||||||
zoomTo = zoomPanHelper.zoomTo
|
|
||||||
setTransform = zoomPanHelper.setTransform
|
|
||||||
setCenter = zoomPanHelper.setCenter
|
|
||||||
fitBounds = zoomPanHelper.fitBounds
|
|
||||||
|
|
||||||
// hide graph until dimensions are ready, so we don't have jumping graphs (ssr for example)
|
// hide graph until dimensions are ready, so we don't have jumping graphs (ssr for example)
|
||||||
ready = true
|
ready = true
|
||||||
|
|
||||||
fitViewOnInit && fitView()
|
fitViewOnInit && fitView()
|
||||||
emits.paneReady({ fitView, zoomIn, zoomOut, zoomTo, setTransform, setCenter, fitBounds, ...rest })
|
emits.paneReady({
|
||||||
|
id,
|
||||||
|
nodes,
|
||||||
|
edges,
|
||||||
|
viewport,
|
||||||
|
snapToGrid,
|
||||||
|
snapGrid,
|
||||||
|
dimensions,
|
||||||
|
setState,
|
||||||
|
fitViewOnInit,
|
||||||
|
fitView,
|
||||||
|
emits,
|
||||||
|
...rest,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ import {
|
|||||||
pointToRendererPoint,
|
pointToRendererPoint,
|
||||||
updateEdgeAction,
|
updateEdgeAction,
|
||||||
} from '~/utils'
|
} from '~/utils'
|
||||||
|
import { useZoomPanHelper } from '~/composables'
|
||||||
|
|
||||||
export default (state: State, getters: ComputedGetters): Actions => {
|
export default (state: State, getters: ComputedGetters, id: string): Actions => {
|
||||||
const updateNodePositions: Actions['updateNodePositions'] = (dragItems, changed, dragging) => {
|
const updateNodePositions: Actions['updateNodePositions'] = (dragItems, changed, dragging) => {
|
||||||
const changes: NodePositionChange[] = []
|
const changes: NodePositionChange[] = []
|
||||||
|
|
||||||
@@ -338,10 +339,20 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const paneNotReady = () => {
|
let zoomPanHelper: ReturnType<typeof useZoomPanHelper>
|
||||||
console.warn(
|
const paneReady = async () => {
|
||||||
`[Vue Flow]: Used viewpane function before pane was ready. Use viewpane functions *after* onPaneReady is emitted.`,
|
const zoompan = useZoomPanHelper(id)
|
||||||
)
|
|
||||||
|
return new Promise<ReturnType<typeof useZoomPanHelper>>((resolve) => {
|
||||||
|
if (!zoomPanHelper) {
|
||||||
|
state.hooks.paneReady.on(() => {
|
||||||
|
resolve(zoompan)
|
||||||
|
zoomPanHelper = zoompan
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolve(zoomPanHelper)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -368,21 +379,40 @@ export default (state: State, getters: ComputedGetters): Actions => {
|
|||||||
removeSelectedEdges,
|
removeSelectedEdges,
|
||||||
setInteractive,
|
setInteractive,
|
||||||
setState,
|
setState,
|
||||||
fitView: paneNotReady,
|
fitView: async (params = { padding: 0.1 }) => {
|
||||||
zoomIn: paneNotReady,
|
const { fitView } = await paneReady()
|
||||||
zoomOut: paneNotReady,
|
fitView(params)
|
||||||
zoomTo: paneNotReady,
|
},
|
||||||
setTransform: paneNotReady,
|
zoomIn: async (options) => {
|
||||||
|
const { zoomIn } = await paneReady()
|
||||||
|
zoomIn(options)
|
||||||
|
},
|
||||||
|
zoomOut: async (options) => {
|
||||||
|
const { zoomOut } = await paneReady()
|
||||||
|
zoomOut(options)
|
||||||
|
},
|
||||||
|
zoomTo: async (zoomLevel, options) => {
|
||||||
|
const { zoomTo } = await paneReady()
|
||||||
|
zoomTo(zoomLevel, options)
|
||||||
|
},
|
||||||
|
setTransform: async (transform, options) => {
|
||||||
|
const { setTransform } = await paneReady()
|
||||||
|
setTransform(transform, options)
|
||||||
|
},
|
||||||
getTransform: () => ({
|
getTransform: () => ({
|
||||||
x: state.viewport.x,
|
x: state.viewport.x,
|
||||||
y: state.viewport.y,
|
y: state.viewport.y,
|
||||||
zoom: state.viewport.zoom,
|
zoom: state.viewport.zoom,
|
||||||
}),
|
}),
|
||||||
setCenter: paneNotReady,
|
setCenter: async (x, y, options) => {
|
||||||
fitBounds: paneNotReady,
|
const { setCenter } = await paneReady()
|
||||||
project(position) {
|
setCenter(x, y, options)
|
||||||
return pointToRendererPoint(position, state.viewport, state.snapToGrid, state.snapGrid)
|
|
||||||
},
|
},
|
||||||
|
fitBounds: async (bounds, options) => {
|
||||||
|
const { fitBounds } = await paneReady()
|
||||||
|
fitBounds(bounds, options)
|
||||||
|
},
|
||||||
|
project: (position) => pointToRendererPoint(position, state.viewport, state.snapToGrid, state.snapGrid),
|
||||||
toObject,
|
toObject,
|
||||||
$reset: () => {
|
$reset: () => {
|
||||||
setState(useState())
|
setState(useState())
|
||||||
|
|||||||
Reference in New Issue
Block a user