feat: Enable passing components as node/edge-types

* Instead of using slots (re)-enable passing components for node/edge-types
This commit is contained in:
Braks
2022-03-23 15:49:00 +01:00
parent f3b3062970
commit 6a2c1b00d7
8 changed files with 44 additions and 29 deletions
+15 -17
View File
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import ColorSelectorNode from './ColorSelectorNode.vue'
import { ConnectionMode, Elements, isEdge, Node, Position, SnapGrid, useVueFlow, VueFlow, Controls, MiniMap } from '~/index'
import { ConnectionMode, Controls, Elements, isEdge, MiniMap, Node, Position, SnapGrid, useVueFlow, VueFlow } from '~/index'
const elements = ref<Elements>([])
const bgColor = ref('#1A192B')
@@ -62,25 +62,23 @@ onMounted(() => {
]
})
const { onPaneReady } = useVueFlow()
onPaneReady((flowInstance) => {
flowInstance.fitView()
console.log('flow loaded:', flowInstance)
const { onPaneReady } = useVueFlow({
connectionMode: ConnectionMode.Loose,
connectionLineStyle,
snapToGrid: true,
snapGrid,
defaultZoom: 1.5,
nodeTypes: {
selectorNode: markRaw(ColorSelectorNode),
},
})
onPaneReady((i) => {
i.fitView()
console.log('flow loaded:', i)
})
</script>
<template>
<VueFlow
v-model="elements"
:style="{ backgroundColor: bgColor }"
:connection-mode="ConnectionMode.Loose"
:connection-line-style="connectionLineStyle"
:snap-to-grid="true"
:snap-grid="snapGrid"
:default-zoom="1.5"
>
<template #node-selectorNode="props">
<ColorSelectorNode v-bind="props" />
</template>
<VueFlow v-model="elements" :style="{ backgroundColor: bgColor }">
<MiniMap :node-stroke-color="nodeStroke" :node-color="nodeColor" />
<Controls />
</VueFlow>
+11 -1
View File
@@ -98,7 +98,7 @@ export default (
)
watch(
() => props.paneMovable,
(v) => isDef(v) && (store.paneMoveable = v),
(v) => isDef(v) && (store.paneMovable = v),
{ immediate: isDef(props.paneMovable) },
)
watch(
@@ -206,5 +206,15 @@ export default (
(v) => isDef(v) && (store.applyDefault = v),
{ immediate: isDef(props.applyDefault) },
)
watch(
() => props.nodeTypes,
(v) => isDef(v) && (store.nodeTypes = v),
{ immediate: isDef(props.nodeTypes) },
)
watch(
() => props.edgeTypes,
(v) => isDef(v) && (store.edgeTypes = v),
{ immediate: isDef(props.edgeTypes) },
)
})
}
+2 -2
View File
@@ -121,7 +121,7 @@ onMounted(async () => {
const pinchZoom = store.zoomOnPinch && event.ctrlKey
// if all interactions are disabled, we prevent all zoom events
if (!store.paneMoveable && !store.zoomOnScroll && !store.panOnScroll && !store.zoomOnDoubleClick && !store.zoomOnPinch)
if (!store.paneMovable && !store.zoomOnScroll && !store.panOnScroll && !store.zoomOnDoubleClick && !store.zoomOnPinch)
return false
// during a selection we prevent all other interactions
@@ -148,7 +148,7 @@ onMounted(async () => {
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 (!store.paneMoveable && (event.type === 'mousedown' || event.type === 'touchstart')) return false
if (!store.paneMovable && (event.type === 'mousedown' || event.type === 'touchstart')) return false
// default filter for d3-zoom
return (!event.ctrlKey || event.type === 'wheel') && !event.button
+2 -2
View File
@@ -209,7 +209,7 @@ export default (state: State, getters: ComputedGetters): Actions => {
}
const setElements: Actions['setElements'] = (elements, extent) => {
if (!state.initialized && !elements.length) return
if ((!state.initialized && !elements.length) || !elements) return
setNodes(elements.filter(isNode), extent)
setEdges(elements.filter(isEdge))
}
@@ -255,7 +255,7 @@ export default (state: State, getters: ComputedGetters): Actions => {
if (typeof opts.panOnScroll !== 'undefined') state.panOnScroll = opts.panOnScroll
if (typeof opts.panOnScrollMode !== 'undefined') state.panOnScrollMode = opts.panOnScrollMode
if (typeof opts.panOnScrollSpeed !== 'undefined') state.panOnScrollSpeed = opts.panOnScrollSpeed
if (typeof opts.paneMovable !== 'undefined') state.paneMoveable = opts.paneMovable
if (typeof opts.paneMovable !== 'undefined') state.paneMovable = opts.paneMovable
if (typeof opts.zoomOnScroll !== 'undefined') state.zoomOnScroll = opts.zoomOnScroll
if (typeof opts.preventScrolling !== 'undefined') state.preventScrolling = opts.preventScrolling
if (typeof opts.zoomOnDoubleClick !== 'undefined') state.zoomOnDoubleClick = opts.zoomOnDoubleClick
+2
View File
@@ -6,6 +6,7 @@ export default (state: State): ComputedGetters => {
const getEdgeTypes = computed(() => {
const edgeTypes: Record<string, any> = {
...defaultEdgeTypes,
...state.edgeTypes,
}
const keys = Object.keys(edgeTypes)
state.edges?.forEach((e) => e.type && !keys.includes(e.type) && (edgeTypes[e.type] = e.type))
@@ -15,6 +16,7 @@ export default (state: State): ComputedGetters => {
const getNodeTypes = computed(() => {
const nodeTypes: Record<string, any> = {
...defaultNodeTypes,
...state.nodeTypes,
}
const keys = Object.keys(nodeTypes)
state.nodes?.forEach((n) => n.type && !keys.includes(n.type) && (nodeTypes[n.type] = n.type))
+4 -2
View File
@@ -59,7 +59,7 @@ export default (opts?: FlowOptions): State => {
panOnScroll: false,
panOnScrollSpeed: 0.5,
panOnScrollMode: PanOnScrollMode.Free,
paneMoveable: true,
paneMovable: true,
edgeUpdaterRadius: 10,
onlyRenderVisibleElements: false,
defaultZoom: 1,
@@ -100,10 +100,12 @@ export default (opts?: FlowOptions): State => {
} as State
if (opts) {
if (typeof opts.nodeTypes !== 'undefined') state.nodeTypes = opts.nodeTypes
if (typeof opts.edgeTypes !== 'undefined') state.edgeTypes = opts.edgeTypes
if (typeof opts.panOnScroll !== 'undefined') state.panOnScroll = opts.panOnScroll
if (typeof opts.panOnScrollMode !== 'undefined') state.panOnScrollMode = opts.panOnScrollMode
if (typeof opts.panOnScrollSpeed !== 'undefined') state.panOnScrollSpeed = opts.panOnScrollSpeed
if (typeof opts.paneMovable !== 'undefined') state.paneMoveable = opts.paneMovable
if (typeof opts.paneMovable !== 'undefined') state.paneMovable = opts.paneMovable
if (typeof opts.zoomOnScroll !== 'undefined') state.zoomOnScroll = opts.zoomOnScroll
if (typeof opts.preventScrolling !== 'undefined') state.preventScrolling = opts.preventScrolling
if (typeof opts.zoomOnDoubleClick !== 'undefined') state.zoomOnDoubleClick = opts.zoomOnDoubleClick
+4 -1
View File
@@ -5,6 +5,7 @@ import { ConnectionLineType, ConnectionMode } from './connection'
import { KeyCode, PanOnScrollMode, UseZoomPanHelper } from './zoom'
import { Actions, ComputedGetters, State, FlowStore } from './store'
import { FlowHooksOn } from './hooks'
import { DefaultEdgeTypes, DefaultNodeTypes, EdgeComponent, NodeComponent } from "~/types/components";
export type FlowElement<N = any, E = any> = GraphNode<N> | GraphEdge<E>
export type FlowElements<N = any, E = any> = FlowElement<N, E>[]
@@ -83,11 +84,13 @@ export type FlowInstance<N = any, E = N> = {
} & UseZoomPanHelper
export interface FlowProps<N = any, E = N> {
id?: string
/** @deprecated use nodes / edges instead */
modelValue?: Elements<N, E>
nodes?: Node<N>[]
edges?: Edge<E>[]
id?: string
edgeTypes?: { [key in keyof DefaultEdgeTypes]?: EdgeComponent } & { [key: string]: EdgeComponent }
nodeTypes?: { [key in keyof DefaultNodeTypes]?: NodeComponent } & { [key: string]: NodeComponent }
connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
+4 -4
View File
@@ -1,6 +1,6 @@
import { ComputedRef, CSSProperties, ToRefs } from 'vue'
import { Dimensions, Elements, FlowElements, FlowInstance, FlowOptions, Rect, SnapGrid, Transform, XYPosition } from './flow'
import { HandleType, EdgeComponent, NodeComponent } from './components'
import { HandleType, EdgeComponent, NodeComponent, DefaultNodeTypes, DefaultEdgeTypes } from './components'
import { Connection, ConnectionLineType, ConnectionMode, SetConnectionId } from './connection'
import { Edge, GraphEdge } from './edge'
import { GraphNode, CoordinateExtent, Node } from './node'
@@ -54,7 +54,7 @@ export interface State<N = any, E = N> extends Omit<FlowOptions<N, E>, 'id' | 'm
nodesConnectable: boolean
elementsSelectable: boolean
selectNodesOnDrag: boolean
paneMoveable: boolean
paneMovable: boolean
zoomOnScroll: boolean
zoomOnPinch: boolean
panOnScroll: boolean
@@ -95,8 +95,8 @@ export interface Actions<N = any, E = N> {
}
export interface Getters<N = any, E = N> {
getEdgeTypes: Record<string, EdgeComponent>
getNodeTypes: Record<string, NodeComponent>
getEdgeTypes: Record<keyof DefaultEdgeTypes | string, EdgeComponent>
getNodeTypes: Record<keyof DefaultNodeTypes | string, NodeComponent>
getNodes: GraphNode<N>[]
getEdges: GraphEdge<E>[]
getNode: (id: string) => GraphNode<N> | undefined