feat(types): Add NodeTypes and EdgeTypes

* Interface for passing an object of NodeTypes/EdgeTypes
* Object needs to be passed with components markedRaw

Signed-off-by: Braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
Braks
2021-11-19 17:47:57 +01:00
parent 8c4747a8a9
commit 37388ddf47
17 changed files with 69 additions and 74 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ const bgColor = ref('#1A192B')
const connectionLineStyle = { stroke: '#fff' }
const snapGrid: SnapGrid = [16, 16]
const nodeTypes = {
selectorNode: ColorSelectorNode,
selectorNode: markRaw(ColorSelectorNode),
}
const onLoad = (flowInstance: FlowInstance) => {
@@ -2,7 +2,7 @@
import { CSSProperties } from 'vue'
import NodeA from './NodeA.vue'
import NodeB from './NodeB.vue'
import { VueFlow, Elements, Position, NodeType, Connection, Edge, addEdge } from '~/index'
import { VueFlow, Elements, Position, Connection, Edge, addEdge, NodeTypes } from '~/index'
const initialElements: Elements = [
{
@@ -25,16 +25,13 @@ const initialElements: Elements = [
const buttonStyle: CSSProperties = { position: 'absolute', right: 10, top: 30, zIndex: 4 }
const nodeStyles: CSSProperties = { padding: '10px 15px', border: '1px solid #ddd' }
type NodeTypesObject = {
[key: string]: Record<string, NodeType>
}
const nodeTypesObjects: NodeTypesObject = {
const nodeTypesObjects: Record<string, NodeTypes> = {
a: {
a: NodeA as NodeType,
a: NodeA,
},
b: {
b: NodeB as NodeType,
b: NodeB,
},
}
@@ -14,6 +14,7 @@ import {
ConnectionMode,
updateEdge,
ArrowHeadType,
NodeTypes,
} from '~/index'
const initialElements: Elements = [
@@ -172,8 +173,8 @@ const initialElements: Elements = [
},
]
const nodeTypes: Record<string, NodeType> = {
custom: CustomNode as NodeType,
const nodeTypes: NodeTypes = {
custom: CustomNode,
}
let id = 4
@@ -14,6 +14,7 @@ import {
Position,
isEdge,
FlowInstance,
NodeTypes,
} from '~/index'
const initialHandleCount = 1
@@ -29,8 +30,8 @@ const initialElements: Elements = [
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 10 }
const nodeTypes: Record<string, NodeType> = {
custom: CustomNode as NodeType,
const nodeTypes: NodeTypes = {
custom: CustomNode,
}
let id = 5
+4 -3
View File
@@ -13,6 +13,7 @@ import {
NodeProps,
FlowInstance,
NodeType,
NodeTypes,
} from '~/index'
import './validation.css'
@@ -34,9 +35,9 @@ const onConnect = (params: Connection | Edge) => {
console.log('on connect', params)
elements.value = addEdge(params, elements.value)
}
const nodeTypes: Record<string, NodeType> = {
custominput: CustomInput as NodeType,
customnode: CustomNode as NodeType,
const nodeTypes: NodeTypes = {
custominput: CustomInput,
customnode: CustomNode,
}
</script>
<template>
+9 -3
View File
@@ -1,12 +1,11 @@
<script lang="ts" setup>
import { useHandle, useStore } from '../../composables'
import { ConnectionMode, Edge, EdgePositions, EdgeType, Position } from '../../types'
import { ConnectionMode, Edge, EdgePositions, Position } from '../../types'
import EdgeAnchor from './EdgeAnchor.vue'
import { getEdgePositions, getHandle, getSourceTargetNodes, isEdgeVisible } from '~/container/EdgeRenderer/utils'
import { isEdge } from '~/utils'
interface EdgeProps {
type: EdgeType
edge: Edge
markerEndId?: string
edgeUpdaterRadius?: number
@@ -16,6 +15,12 @@ const props = withDefaults(defineProps<EdgeProps>(), {})
const store = useStore()
const edgeType = props.edge.type || 'default'
const type = store.getEdgeTypes[edgeType] || store.getEdgeTypes.default
if (!store.getEdgeTypes[edgeType]) {
console.warn(`Edge type "${edgeType}" not found. Using fallback type "default".`)
}
const onEdgeClick = (event: MouseEvent) => {
if (store.elementsSelectable) {
store.unsetNodesSelection()
@@ -166,7 +171,8 @@ const elementsSelectable = computed(() => store.elementsSelectable)
}"
>
<component
:is="props.type"
:is="type"
v-if="typeof type !== 'boolean'"
v-bind="{
id: props.edge.id,
source: props.edge.source,
+1 -1
View File
@@ -19,7 +19,7 @@ const props = withDefaults(defineProps<HandleProps>(), {
})
const store = useStore()
const nodeId = inject(NodeId)!
const nodeId = inject(NodeId, '')!
const handler = useHandle()
const onMouseDownHandler = (event: MouseEvent) =>
+9 -3
View File
@@ -1,12 +1,11 @@
<script lang="ts" setup>
import { DraggableEventListener, DraggableCore } from '@braks/revue-draggable'
import { useStore } from '../../composables'
import { Node, NodeType, SnapGrid } from '../../types'
import { Node, SnapGrid } from '../../types'
import { NodeId } from '../../context'
interface NodeProps {
node: Node
type: NodeType
selectNodesOnDrag?: boolean
snapGrid?: SnapGrid
}
@@ -21,6 +20,12 @@ provide(NodeId, props.node.id)
const nodeElement = templateRef<HTMLDivElement>('node-element', null)
const nodeType = props.node.type || 'default'
const type = store.getNodeTypes[nodeType] || store.getNodeTypes.default
if (!store.getNodeTypes[nodeType]) {
console.warn(`Node type "${nodeType}" not found. Using fallback type "default".`)
}
const selectable = computed(() =>
typeof props.node.selectable === 'undefined' ? store.elementsSelectable : props.node.selectable,
)
@@ -184,7 +189,8 @@ onMounted(() => {
}"
>
<component
:is="props.type"
:is="type"
v-if="typeof type !== 'boolean'"
v-bind="{
id: props.node.id,
data: props.node.data,
@@ -28,14 +28,6 @@ const connectionLineVisible = computed(
)
const dimensions = computed(() => store.dimensions)
const transform = computed(() => `translate(${store.transform[0]},${store.transform[1]}) scale(${store.transform[2]})`)
const type = (edge: TEdge) => {
const edgeType = edge.type || 'default'
const type = store.getEdgeTypes[edgeType] || store.getEdgeTypes.default
if (!store.getEdgeTypes[edgeType]) {
console.warn(`Edge type "${edgeType}" not found. Using fallback type "default".`)
}
return type
}
</script>
<template>
<svg :width="dimensions.width" :height="dimensions.height" class="vue-flow__edges">
@@ -45,7 +37,6 @@ const type = (edge: TEdge) => {
v-for="edge of store.getEdges"
:key="edge.id"
:edge="edge"
:type="type(edge)"
:marker-end-id="props.markerEndId"
:edge-updater-radius="props.edgeUpdaterRadius"
>
@@ -1,6 +1,5 @@
<script lang="ts" setup>
import { invoke } from '@vueuse/core'
import { Node as TNode } from '../../types'
import { useStore } from '../../composables'
import Node from '../../components/Nodes/Node.vue'
@@ -17,14 +16,6 @@ const store = useStore()
const transform = computed(() => `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`)
const snapGrid = computed(() => (store.snapToGrid ? store.snapGrid : undefined))
const type = (node: TNode) => {
const nodeType = node.type || 'default'
const type = store.getNodeTypes[nodeType] || store.getNodeTypes.default
if (!store.getNodeTypes[nodeType]) {
console.warn(`Node type "${nodeType}" not found. Using fallback type "default".`)
}
return type
}
invoke(async () => {
await until(store.getNodes).toMatch((y) => y.length > 0)
await until(store.transform).toMatch(([x, y, z]) => x !== 0 && y !== 0 && z !== 1)
@@ -37,7 +28,6 @@ invoke(async () => {
v-for="node of store.getNodes"
:key="node.id"
:node="node"
:type="type(node)"
:snap-grid="snapGrid"
:select-nodes-on-drag="props.selectNodesOnDrag"
>
+4 -4
View File
@@ -6,12 +6,12 @@ import {
ConnectionMode,
Elements,
PanOnScrollMode,
NodeType,
EdgeType,
KeyCode,
TranslateExtent,
NodeExtent,
FlowOptions,
NodeTypes,
EdgeTypes,
} from '../../types'
import ZoomPane from '../../container/ZoomPane/ZoomPane.vue'
import SelectionPane from '../../container/SelectionPane/SelectionPane.vue'
@@ -22,8 +22,8 @@ import { createHooks, initFlow } from '../../composables'
export interface FlowProps extends Partial<FlowOptions> {
modelValue?: Elements
elements?: Elements
nodeTypes?: Record<string, NodeType>
edgeTypes?: Record<string, EdgeType>
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties
+3 -3
View File
@@ -1,7 +1,7 @@
import { setActivePinia, createPinia, defineStore, StoreDefinition } from 'pinia'
import diff from 'microdiff'
import { parseElements } from './utils'
import { FlowState, Node, FlowActions, Elements, NodeType, EdgeType, FlowGetters, Edge } from '~/types'
import { FlowState, Node, FlowActions, Elements, FlowGetters, Edge, EdgeTypes, NodeTypes } from '~/types'
import { clampPosition, getDimensions, getConnectedEdges, getNodesInside, getRectOfNodes, isNode } from '~/utils'
import { getHandleBounds } from '~/components/Nodes/utils'
import { defaultEdgeTypes, defaultNodeTypes } from '~/store/index'
@@ -23,10 +23,10 @@ export default function flowStore(
...preloadedState,
}),
getters: {
getEdgeTypes(): Record<string, EdgeType> {
getEdgeTypes(): EdgeTypes {
return { ...defaultEdgeTypes, ...this.edgeTypes }
},
getNodeTypes(): Record<string, NodeType> {
getNodeTypes(): NodeTypes {
return { ...defaultNodeTypes, ...this.nodeTypes }
},
getNodes(): Node[] {
+10 -10
View File
@@ -1,19 +1,19 @@
import { ConnectionMode, EdgeType, FlowState, NodeType } from '~/types'
import { ConnectionMode, EdgeTypes, FlowState, NodeTypes } from '~/types'
import { createHooks } from '~/composables'
import { DefaultNode, InputNode, OutputNode } from '~/components/Nodes'
import { BezierEdge, SmoothStepEdge, StepEdge, StraightEdge } from '~/components/Edges'
export const defaultNodeTypes: Record<string, NodeType> = {
input: InputNode as NodeType,
default: DefaultNode as NodeType,
output: OutputNode as NodeType,
export const defaultNodeTypes: NodeTypes = {
input: markRaw(InputNode),
default: markRaw(DefaultNode),
output: markRaw(OutputNode),
}
export const defaultEdgeTypes: Record<string, EdgeType> = {
default: BezierEdge as EdgeType,
straight: StraightEdge as EdgeType,
step: StepEdge as EdgeType,
smoothstep: SmoothStepEdge as EdgeType,
export const defaultEdgeTypes: EdgeTypes = {
default: markRaw(BezierEdge),
straight: markRaw(StraightEdge),
step: markRaw(StepEdge),
smoothstep: markRaw(SmoothStepEdge),
}
export const initialState = (): FlowState => ({
+3 -2
View File
@@ -1,4 +1,4 @@
import { CSSProperties, DefineComponent } from 'vue'
import { Component, CSSProperties, DefineComponent } from 'vue'
import { ArrowHeadType, ElementId, Position } from './types'
export interface Edge<T = any> {
@@ -48,7 +48,8 @@ export interface EdgeSmoothStepProps<T = any> extends EdgeProps<T> {
borderRadius?: number
}
export type EdgeType = DefineComponent<EdgeSmoothStepProps, any, any, any, any, any> | boolean
export type EdgeType = Component<EdgeProps> | DefineComponent<EdgeSmoothStepProps, any, any, any, any, any> | boolean
export type EdgeTypes = Record<string, EdgeType>
export interface EdgePositions {
sourceX: number
+3 -2
View File
@@ -1,4 +1,4 @@
import { DefineComponent } from 'vue'
import { Component, DefineComponent } from 'vue'
import { XYPosition, ElementId, Position } from './types'
export interface Node<T = any> {
@@ -58,4 +58,5 @@ export interface NodeProps<T = any> {
dragging?: boolean
}
export type NodeType = DefineComponent<NodeProps, any, any, any, any> | boolean
export type NodeType = Component<NodeProps> | DefineComponent<NodeProps, any, any, any, any> | boolean
export type NodeTypes = Record<string, NodeType>
+6 -6
View File
@@ -13,8 +13,8 @@ import {
} from './types'
import { HandleType } from './handle'
import { ConnectionMode, OnConnectEndFunc, OnConnectFunc, OnConnectStartFunc, OnConnectStopFunc } from './connection'
import { Edge, EdgeType } from './edge'
import { Node, NodeExtent, NodeType, TranslateExtent } from './node'
import { Edge, EdgeTypes } from './edge'
import { Node, NodeExtent, NodeTypes, TranslateExtent } from './node'
import { FlowActions } from './actions'
import { D3Selection, D3Zoom, D3ZoomHandler } from './panel'
import { FlowHooks } from './hooks'
@@ -24,9 +24,9 @@ export interface FlowState extends FlowOptions {
transform: Transform
elements: Elements
nodes: Node[]
nodeTypes: Record<string, NodeType>
nodeTypes: NodeTypes
edges: Edge[]
edgeTypes: Record<string, EdgeType>
edgeTypes: EdgeTypes
selectedElements?: Elements
selectedNodesBbox: Rect
@@ -72,8 +72,8 @@ export interface FlowState extends FlowOptions {
}
export interface FlowGetters {
getEdgeTypes: () => Record<string, EdgeType>
getNodeTypes: () => Record<string, NodeType>
getEdgeTypes: () => EdgeTypes
getNodeTypes: () => NodeTypes
getNodes: () => Node[]
getEdges: () => Edge[]
}
+6 -6
View File
@@ -1,6 +1,6 @@
import { CSSProperties, HTMLAttributes } from 'vue'
import { Edge, EdgeType } from './edge'
import { Node, NodeExtent, NodeType, TranslateExtent } from './node'
import { CSSProperties } from 'vue'
import { Edge, EdgeTypes } from './edge'
import { Node, NodeExtent, NodeTypes, TranslateExtent } from './node'
import { ConnectionLineType, ConnectionMode } from './connection'
import { KeyCode, PanOnScrollMode } from './panel'
@@ -88,10 +88,10 @@ export type FlowInstance<T = any> = {
toObject: ToObjectFunc<T>
}
export interface FlowOptions extends Omit<HTMLAttributes, 'onLoad'> {
export interface FlowOptions {
elements: Elements
nodeTypes?: Record<string, NodeType>
edgeTypes?: Record<string, EdgeType>
nodeTypes?: NodeTypes
edgeTypes?: EdgeTypes
connectionMode?: ConnectionMode
connectionLineType?: ConnectionLineType
connectionLineStyle?: CSSProperties