refactor(types): Remove internal __vf field

* fields are merged into the GraphNode / Node interface
* Remove passing props from VueFlow container, use injected state

Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
Braks
2021-12-20 19:29:52 +01:00
parent 3f0b0dbd70
commit f28e10b05a
17 changed files with 219 additions and 478 deletions
+20 -70
View File
@@ -1,75 +1,37 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import {
ConnectionLineType,
ConnectionMode,
Dimensions,
EdgeComponent,
GraphEdge,
GraphNode,
HandleType,
Transform,
XYPosition,
} from '../../types'
import EdgeWrapper from '../../components/Edges/EdgeWrapper.vue'
import ConnectionLine from '../../components/ConnectionLine/ConnectionLine.vue'
import { useStore } from '../../composables'
import MarkerDefinitions from './MarkerDefinitions.vue'
interface EdgeRendererProps {
edges: GraphEdge[]
nodes: GraphNode[]
edgeTypes: Record<string, EdgeComponent>
transform: Transform
dimensions: Dimensions
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
arrowHeadColor?: string
markerEndId?: string
elementsSelectable?: boolean
edgeUpdaterRadius?: number
connectionNodeId?: string
connectionHandleType?: HandleType
connectionHandleId?: string
connectionPosition?: XYPosition
connectionMode: ConnectionMode
nodesConnectable?: boolean
edgesUpdatable?: boolean
}
const props = withDefaults(defineProps<EdgeRendererProps>(), {
arrowHeadColor: '#b1b1b7',
connectionLineType: ConnectionLineType.Bezier,
edgeUpdaterRadius: 10,
handleEdgeUpdate: false,
})
const store = useStore()
const getType = (type?: string) => {
const t = type ?? 'default'
let edgeType = props.edgeTypes[t]
let edgeType = store.getEdgeTypes[t]
if (!edgeType) {
edgeType = props.edgeTypes.default
edgeType = store.getEdgeTypes.default
console.warn(`Edge type "${type}" not found. Using fallback type "default".`)
}
return edgeType
}
const sourceNode = controlledComputed(
() => props.connectionNodeId,
() => store.connectionNodeId,
() => {
if (props.connectionNodeId) return props.nodes[props.nodes.map((n) => n.id).indexOf(props.connectionNodeId)]
if (store.connectionNodeId) return store.getNodes[store.getNodes.map((n) => n.id).indexOf(store.connectionNodeId)]
},
)
const connectionLineVisible = controlledComputed(
() => props.connectionNodeId,
() => store.connectionNodeId,
() =>
!!(
sourceNode.value &&
(typeof sourceNode.value.connectable === 'undefined' ? props.nodesConnectable : sourceNode.value.connectable) &&
props.connectionNodeId &&
props.connectionHandleType
(typeof sourceNode.value.connectable === 'undefined' ? store.nodesConnectable : sourceNode.value.connectable) &&
store.connectionNodeId &&
store.connectionHandleType
),
)
const transform = computed(() => `translate(${props.transform[0]},${props.transform[1]}) scale(${props.transform[2]})`)
const transform = computed(() => `translate(${store.transform[0]},${store.transform[1]}) scale(${store.transform[2]})`)
</script>
<script lang="ts">
export default {
@@ -77,37 +39,25 @@ export default {
}
</script>
<template>
<svg :width="props.dimensions.width" :height="props.dimensions.height" class="vue-flow__edges">
<MarkerDefinitions :color="props.arrowHeadColor" />
<svg :width="store.dimensions.width" :height="store.dimensions.height" class="vue-flow__edges">
<MarkerDefinitions :color="store.arrowHeadColor" />
<g :transform="transform">
<EdgeWrapper
v-for="(edge, i) of props.edges"
v-for="(edge, i) of store.getEdges"
:key="`${edge.id}-${i}`"
:edge="edge"
:component="getType(edge.type)"
:selectable="props.elementsSelectable"
:updatable="typeof edge.updatable === 'undefined' ? props.edgesUpdatable : edge.updatable"
:edge-updater-radius="props.edgeUpdaterRadius"
:dimensions="props.dimensions"
:transform="props.transform"
:selectable="store.elementsSelectable"
:updatable="typeof edge.updatable === 'undefined' ? store.edgesUpdatable : edge.updatable"
:edge-updater-radius="store.edgeUpdaterRadius"
:dimensions="store.dimensions"
:transform="store.transform"
>
<template #default="edgeProps">
<slot :name="`edge-${edge.type}`" v-bind="edgeProps"></slot>
</template>
</EdgeWrapper>
<ConnectionLine
v-if="connectionLineVisible && sourceNode"
:source-node="sourceNode"
:connection-line-style="props.connectionLineStyle"
:connection-line-type="props.connectionLineType"
:connection-handle-id="props.connectionHandleId"
:connection-node-id="props.connectionNodeId"
:connection-handle-type="props.connectionHandleType"
:connection-position="props.connectionPosition"
:connection-mode="props.connectionMode"
:nodes="props.nodes"
:transform="props.transform"
>
<ConnectionLine v-if="connectionLineVisible && sourceNode" :source-node="sourceNode">
<template #default="customConnectionLineProps">
<slot name="custom-connection-line" v-bind="customConnectionLineProps"></slot>
</template>
+13 -32
View File
@@ -1,40 +1,21 @@
<script lang="ts" setup>
import { GraphNode, NodeComponent, SnapGrid, Transform } from '../../types'
import { GraphNode } from '../../types'
import NodeWrapper from '../../components/Nodes/NodeWrapper.vue'
import { useStore } from '../../composables'
interface NodeRendererProps {
nodes?: GraphNode[]
nodeTypes: Record<string, NodeComponent>
selectNodesOnDrag?: boolean
snapToGrid?: boolean
snapGrid?: SnapGrid
transform: Transform
elementsSelectable?: boolean
nodesDraggable?: boolean
nodesConnectable?: boolean
}
const props = withDefaults(defineProps<NodeRendererProps>(), {
selectNodesOnDrag: true,
nodesConnectable: true,
nodesDraggable: true,
elementsSelectable: true,
snapToGrid: false,
snapGrid: () => [15, 15],
})
const store = useStore()
const getType = (type?: string) => {
const t = type ?? 'default'
let nodeType = props.nodeTypes[t]
let nodeType = store.getNodeTypes[t]
if (!nodeType) {
nodeType = props.nodeTypes.default
nodeType = store.getNodeTypes.default
console.warn(`Node type "${type}" not found. Using fallback type "default".`)
}
return nodeType
}
const transform = computed(() => `translate(${props.transform[0]}px,${props.transform[1]}px) scale(${props.transform[2]})`)
const snapGrid = (node: GraphNode) => node.snapGrid ?? (props.snapToGrid ? props.snapGrid : undefined)
const transform = computed(() => `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`)
const snapGrid = (node: GraphNode) => node.snapGrid ?? (store.snapToGrid ? store.snapGrid : undefined)
</script>
<script lang="ts">
export default {
@@ -44,16 +25,16 @@ export default {
<template>
<div class="vue-flow__nodes" :style="{ transform }">
<NodeWrapper
v-for="(node, i) of props.nodes"
v-for="(node, i) of store.getNodes"
:key="`${node.id}-${i}`"
:node="node"
:component="getType(node.type)"
:draggable="typeof node.draggable === 'undefined' ? props.nodesDraggable : node.draggable"
:selectable="typeof node.selectable === 'undefined' ? props.elementsSelectable : node.selectable"
:connectable="typeof node.connectable === 'undefined' ? props.nodesConnectable : node.connectable"
:draggable="typeof node.draggable === 'undefined' ? store.nodesDraggable : node.draggable"
:selectable="typeof node.selectable === 'undefined' ? store.elementsSelectable : node.selectable"
:connectable="typeof node.connectable === 'undefined' ? store.nodesConnectable : node.connectable"
:snap-grid="snapGrid(node)"
:select-nodes-on-drag="props.selectNodesOnDrag"
:scale="props.transform[2]"
:select-nodes-on-drag="store.selectNodesOnDrag"
:scale="store.transform[2]"
>
<template #default="nodeProps">
<slot :name="`node-${node.type}`" v-bind="nodeProps"></slot>
+10 -33
View File
@@ -5,24 +5,6 @@ import { getConnectedEdges, isGraphNode } from '../../utils'
import NodesSelection from '../../components/NodesSelection/NodesSelection.vue'
import UserSelection from '../../components/UserSelection/UserSelection.vue'
interface SelectionPaneProps {
edges: GraphEdge[]
selectedElements?: FlowElements
selectionKeyCode?: KeyCode
deleteKeyCode?: KeyCode
multiSelectionKeyCode?: KeyCode
elementsSelectable?: boolean
nodesSelectionActive?: boolean
selectionActive?: boolean
}
const props = withDefaults(defineProps<SelectionPaneProps>(), {
selectionKeyCode: 'Shift',
deleteKeyCode: 'Backspace',
multiSelectionKeyCode: 'Meta',
elementsSelectable: true,
selectedElements: () => [],
})
const store = useStore()
const onClick = (event: MouseEvent) => {
@@ -38,11 +20,11 @@ const onWheel = (event: WheelEvent) => store.hooks.paneScroll.trigger(event)
const userSelection = ref(false)
tryOnMounted(() => {
useKeyPress(props.deleteKeyCode, (keyPressed) => {
if (keyPressed && props.selectedElements) {
const selectedNodes = props.selectedElements.filter(isGraphNode)
const connectedEdges = getConnectedEdges(selectedNodes, props.edges)
const elementsToRemove = [...props.selectedElements, ...connectedEdges].reduce(
useKeyPress(store.deleteKeyCode, (keyPressed) => {
if (keyPressed && store.selectedElements) {
const selectedNodes = store.selectedElements.filter(isGraphNode)
const connectedEdges = getConnectedEdges(selectedNodes, store.getEdges)
const elementsToRemove = [...store.selectedElements, ...connectedEdges].reduce(
(res, item) => res.set(item.id, item),
new Map<string, FlowElement>(),
)
@@ -53,12 +35,12 @@ tryOnMounted(() => {
}
})
useKeyPress(props.multiSelectionKeyCode, (keyPressed) => {
useKeyPress(store.multiSelectionKeyCode, (keyPressed) => {
store.multiSelectionActive = keyPressed
})
useKeyPress(props.selectionKeyCode, (keyPressed) => {
userSelection.value = keyPressed && (props.selectionActive || props.elementsSelectable)
useKeyPress(store.selectionKeyCode, (keyPressed) => {
userSelection.value = keyPressed && (store.selectionActive || store.elementsSelectable)
})
})
</script>
@@ -70,12 +52,7 @@ export default {
</script>
<template>
<slot></slot>
<UserSelection v-if="userSelection" id="user-selection" :key="`user-selection-${store.id}`" />
<NodesSelection
v-if="props.nodesSelectionActive"
id="nodes-selection"
:key="`nodes-selction-${store.id}`"
:selected-elements="props.selectedElements"
/>
<UserSelection v-if="userSelection" :key="`user-selection-${store.id}`" />
<NodesSelection v-if="store.nodesSelectionActive" :key="`nodes-selction-${store.id}`" />
<div :key="`flow-pane-${store.id}`" class="vue-flow__pane" @click="onClick" @contextmenu="onContextMenu" @wheel="onWheel" />
</template>
+5 -113
View File
@@ -1,16 +1,4 @@
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import {
ConnectionLineType,
ConnectionMode,
Elements,
PanOnScrollMode,
KeyCode,
CoordinateExtent,
NodeTypes,
EdgeTypes,
FlowOptions,
} from '../../types'
import Renderer from '../Renderer/Renderer.vue'
import ZoomPane from '../ZoomPane/ZoomPane.vue'
import SelectionPane from '../SelectionPane/SelectionPane.vue'
@@ -18,47 +6,7 @@ import NodeRenderer from '../NodeRenderer/NodeRenderer.vue'
import EdgeRenderer from '../EdgeRenderer/EdgeRenderer.vue'
import LoadingIndicator from '../../components/Loading/LoadingIndicator.vue'
import { createHooks, initFlow } from '../../composables'
interface FlowProps extends FlowOptions {
id?: string
modelValue?: Elements
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
deleteKeyCode?: KeyCode
selectionKeyCode?: KeyCode
multiSelectionKeyCode?: KeyCode
zoomActivationKeyCode?: KeyCode
preventScrolling?: boolean
snapToGrid?: boolean
snapGrid?: [number, number]
onlyRenderVisibleElements?: boolean
edgesUpdatable?: boolean
nodesDraggable?: boolean
nodesConnectable?: boolean
elementsSelectable?: boolean
selectNodesOnDrag?: boolean
paneMoveable?: boolean
minZoom?: number
maxZoom?: number
defaultZoom?: number
defaultPosition?: [number, number]
translateExtent?: CoordinateExtent
nodeExtent?: CoordinateExtent
arrowHeadColor?: string
markerEndId?: string
zoomOnScroll?: boolean
zoomOnPinch?: boolean
panOnScroll?: boolean
panOnScrollSpeed?: number
panOnScrollMode?: PanOnScrollMode
zoomOnDoubleClick?: boolean
edgeUpdaterRadius?: number
storageKey?: string
loading?: string
}
import type { FlowProps } from '../../types/flow'
const props = withDefaults(defineProps<FlowProps>(), {
modelValue: () => [],
@@ -119,45 +67,10 @@ export default {
<Suspense timeout="0">
<template #default>
<Renderer :key="`renderer-${store.id}`" :elements="elements">
<ZoomPane
:key="`zoom-pane-${store.id}`"
:prevent-scrolling="store.preventScrolling"
:selection-key-code="store.selectionKeyCode"
:zoom-activation-key-code="store.zoomActivationKeyCode"
:default-zoom="store.defaultZoom"
:default-position="store.defaultPosition"
:zoom-on-scroll="store.zoomOnScroll"
:zoom-on-pinch="store.zoomOnPinch"
:zoom-on-double-click="store.zoomOnDoubleClick"
:pan-on-scroll="store.panOnScroll"
:pan-on-scroll-speed="store.panOnScrollSpeed"
:pan-on-scroll-mode="store.panOnScrollMode"
:pane-moveable="store.paneMoveable"
>
<ZoomPane :key="`zoom-pane-${store.id}`">
<template #default="zoomPaneProps">
<SelectionPane
:key="`selection-pane-${store.id}`"
:edges="store.getEdges"
:selected-elements="store.selectedElements"
:selection-active="store.selectionActive"
:nodes-selection-active="store.nodesSelectionActive"
:elements-selectable="store.elementsSelectable"
:delete-key-code="store.deleteKeyCode"
:multi-selection-key-code="store.multiSelectionKeyCode"
:selection-key-code="store.selectionKeyCode"
>
<NodeRenderer
:key="`node-renderer-${store.id}`"
:nodes="store.getNodes"
:node-types="store.getNodeTypes"
:snap-to-grid="store.snapToGrid"
:snap-grid="store.snapGrid"
:select-nodes-on-drag="store.selectNodesOnDrag"
:transform="store.transform"
:elements-selectable="store.elementsSelectable"
:nodes-draggable="store.nodesDraggable"
:nodes-connectable="store.nodesConnectable"
>
<SelectionPane :key="`selection-pane-${store.id}`">
<NodeRenderer :key="`node-renderer-${store.id}`">
<template
v-for="nodeName of Object.keys(store.getNodeTypes)"
#[`node-${nodeName}`]="nodeProps"
@@ -166,28 +79,7 @@ export default {
<slot :name="`node-${nodeName}`" v-bind="nodeProps" />
</template>
</NodeRenderer>
<EdgeRenderer
:key="`edge-renderer-${store.id}`"
:transform="store.transform"
:dimensions="store.dimensions"
:edges="store.getEdges"
:edge-types="store.getEdgeTypes"
:nodes="store.getNodes"
:selected-elements="store.selectedElements"
:elements-selectable="store.elementsSelectable"
:connection-node-id="store.connectionNodeId"
:connction-handle-id="store.connectionHandleId"
:connection-handle-type="store.connectionHandleType"
:connection-position="store.connectionPosition"
:connection-mode="store.connectionMode"
:nodes-connectable="store.nodesConnectable"
:connection-line-type="store.connectionLineType"
:connection-line-style="store.connectionLineStyle"
:arrow-head-color="store.arrowHeadColor"
:marker-end-id="store.markerEndId"
:only-render-visible-elements="store.onlyRenderVisibleElements"
:edges-updatable="store.edgesUpdatable"
>
<EdgeRenderer :key="`edge-renderer-${store.id}`">
<template
v-for="edgeName of Object.keys(store.getEdgeTypes)"
#[`edge-${edgeName}`]="edgeProps"
+44 -77
View File
@@ -1,39 +1,10 @@
<script lang="ts" setup>
import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom'
import { pointer, select } from 'd3-selection'
import { FlowTransform, KeyCode, PanOnScrollMode } from '../../types'
import { FlowTransform, PanOnScrollMode } from '../../types'
import { useKeyPress, useStore, useWindow } from '../../composables'
import { clamp } from '../../utils'
import { clamp, clampPosition } from '../../utils'
interface ZoomPaneProps {
selectionKeyCode?: KeyCode
zoomActivationKeyCode?: KeyCode
paneMoveable?: boolean
defaultZoom?: number
defaultPosition?: [number, number]
zoomOnScroll?: boolean
zoomOnPinch?: boolean
panOnScroll?: boolean
panOnScrollSpeed?: number
panOnScrollMode?: PanOnScrollMode
zoomOnDoubleClick?: boolean
preventScrolling?: boolean
}
const props = withDefaults(defineProps<ZoomPaneProps>(), {
selectionKeyCode: 'Shift',
zoomActivationKeyCode: 'Meta',
defaultZoom: 1,
defaultPosition: () => [0, 0],
zoomOnScroll: true,
zoomOnPinch: true,
zoomOnDoubleClick: true,
panOnScroll: false,
panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free,
paneMoveable: true,
preventScrolling: true,
})
const store = useStore()
const zoomPaneEl = templateRef<HTMLDivElement>('zoomPane', null)
@@ -50,10 +21,11 @@ const eventToFlowTransform = (eventTransform: ZoomTransform): FlowTransform => (
const noWheel = (event: Event) => (event.target as Element).closest('.nowheel')
const clampedX = clamp(props.defaultPosition[0], store.translateExtent[0][0], store.translateExtent[1][0])
const clampedY = clamp(props.defaultPosition[1], store.translateExtent[0][1], store.translateExtent[1][1])
const clampedZoom = clamp(props.defaultZoom, store.minZoom, store.maxZoom)
const transform = ref({ x: clampedX, y: clampedY, zoom: clampedZoom })
const clampedZoom = clamp(store.defaultZoom, store.minZoom, store.maxZoom)
const transform = ref({
...clampPosition({ x: store.defaultPosition[0], y: store.defaultPosition[1] }, store.translateExtent),
zoom: clampedZoom,
})
const d3Zoom = ref(zoom<HTMLDivElement, any>().scaleExtent([store.minZoom, store.maxZoom]).translateExtent(store.translateExtent))
const d3Selection = ref()
@@ -66,7 +38,7 @@ nextTick(async () => {
const d3s = d3Selection.value!
const d3ZoomHandler = d3s.on('wheel.zoom')
const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom)
const updatedTransform = zoomIdentity.translate(transform.value.x, transform.value.y).scale(transform.value.zoom)
d3z.transform(d3s, updatedTransform)
store.initD3Zoom({ d3Zoom: d3z, d3Selection: d3s, d3ZoomHandler })
store.transform = [updatedTransform.x, updatedTransform.y, updatedTransform.k]
@@ -87,7 +59,7 @@ nextTick(async () => {
}
})
useKeyPress(props.selectionKeyCode, (keyPress) => {
useKeyPress(store.selectionKeyCode, (keyPress) => {
if (keyPress) {
d3z.on('zoom', null)
} else {
@@ -101,8 +73,8 @@ nextTick(async () => {
}
})
useKeyPress(props.zoomActivationKeyCode, (keyPress) => {
if (props.panOnScroll && keyPress) {
useKeyPress(store.zoomActivationKeyCode, (keyPress) => {
if (store.panOnScroll && keyPress) {
d3s
?.on('wheel', (event: WheelEvent) => {
if (noWheel(event)) return
@@ -111,7 +83,7 @@ nextTick(async () => {
const currentZoom = d3s?.property('__zoom').k || 1
if (event.ctrlKey && props.zoomOnPinch) {
if (event.ctrlKey && store.zoomOnPinch) {
const point = pointer(event)
// taken from https://github.com/d3/d3-zoom/blob/master/src/zoom.js
const pinchDelta = -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * 10
@@ -124,40 +96,40 @@ nextTick(async () => {
// increase scroll speed in firefox
// firefox: deltaMode === 1; chrome: deltaMode === 0
const deltaNormalize = event.deltaMode === 1 ? 20 : 1
const deltaX = props.panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize
const deltaY = props.panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize
const deltaX = store.panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize
const deltaY = store.panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize
if (d3s && props.panOnScrollSpeed)
if (d3s && store.panOnScrollSpeed)
d3z?.translateBy(
d3s,
-(deltaX / currentZoom) * props.panOnScrollSpeed,
-(deltaY / currentZoom) * props.panOnScrollSpeed,
-(deltaX / currentZoom) * store.panOnScrollSpeed,
-(deltaY / currentZoom) * store.panOnScrollSpeed,
)
})
.on('wheel.zoom', null)
} else if (typeof d3ZoomHandler !== 'undefined') {
d3s
?.on('wheel', (event: WheelEvent) => {
if ((!props.zoomOnScroll && props.preventScrolling) || !props.preventScrolling || noWheel(event)) return
if ((!store.zoomOnScroll && store.preventScrolling) || !store.preventScrolling || noWheel(event)) return
event.preventDefault()
})
.on('wheel.zoom', d3ZoomHandler)
}
})
const keyPress = useKeyPress(props.selectionKeyCode)
const keyPress = useKeyPress(store.selectionKeyCode)
d3z.filter((event: MouseEvent) => {
const pinchZoom = props.zoomOnPinch && event.ctrlKey
const pinchZoom = store.zoomOnPinch && event.ctrlKey
// if all interactions are disabled, we prevent all zoom events
if (!props.paneMoveable && !props.zoomOnScroll && !props.panOnScroll && !props.zoomOnDoubleClick && !props.zoomOnPinch)
if (!store.paneMoveable && !store.zoomOnScroll && !store.panOnScroll && !store.zoomOnDoubleClick && !store.zoomOnPinch)
return false
// during a selection we prevent all other interactions
if (keyPress.value) return false
// if zoom on double click is disabled, we prevent the double click event
if (!props.zoomOnDoubleClick && event.type === 'dblclick') return false
if (!store.zoomOnDoubleClick && event.type === 'dblclick') return false
if (noWheel(event) && event.type === 'wheel') return false
@@ -171,13 +143,13 @@ nextTick(async () => {
// when the target element is a node selection, we still allow zooming
if ((event.target as Element).closest('.vue-flow__nodesselection') && event.type !== 'wheel') return false
if (!props.zoomOnPinch && event.ctrlKey && event.type === 'wheel') return false
if (!store.zoomOnPinch && event.ctrlKey && event.type === 'wheel') return false
// when there is no scroll handling enabled, we prevent all wheel events
if (!props.zoomOnScroll && !props.panOnScroll && !pinchZoom && event.type === 'wheel') return false
if (!store.zoomOnScroll && !store.panOnScroll && !pinchZoom && event.type === 'wheel') return false
// if the pane is not movable, we prevent dragging it with mousestart or touchstart
if (!props.paneMoveable && (event.type === 'mousedown' || event.type === 'touchstart')) return false
if (!store.paneMoveable && (event.type === 'mousedown' || event.type === 'touchstart')) return false
// default filter for d3-zoom
return (!event.ctrlKey || event.type === 'wheel') && !event.button
@@ -190,24 +162,24 @@ const { width, height } = useElementBounding(zoomPaneEl)
const window = useWindow()
if ('screen' in window) await until(() => store.isReady).toBe(true)
watch(
[width, height],
([newWidth, newHeight]) => {
store.dimensions.width = newWidth
store.dimensions.height = newHeight
},
{ flush: 'sync', immediate: true },
)
watch(
transform,
(val) =>
(store.transform = [
clamp(val.x, store.translateExtent[0][0], store.translateExtent[1][0]),
clamp(val.y, store.translateExtent[0][1], store.translateExtent[1][1]),
clamp(val.zoom, store.minZoom, store.maxZoom),
]),
{ flush: 'sync', immediate: true },
)
nextTick(() => {
watch(
[width, height],
([newWidth, newHeight]) => {
store.dimensions.width = newWidth
store.dimensions.height = newHeight
},
{ flush: 'sync', immediate: true },
)
watch(
transform,
(val) => {
const { x, y } = clampPosition(val, store.translateExtent)
store.transform = [x, y, clamp(val.zoom, store.minZoom, store.maxZoom)]
},
{ flush: 'sync', immediate: true },
)
})
</script>
<script lang="ts">
export default {
@@ -216,11 +188,6 @@ export default {
</script>
<template>
<div ref="zoomPane" class="vue-flow__zoompane">
<slot
v-bind="{
transform: store.transform,
dimensions: { width, height },
}"
/>
<slot />
</div>
</template>