feat: Allow node/edge template per element
* Allow templates to be overwritten per element with template option
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
const baseRules = {
|
||||
'no-console': 0,
|
||||
'chai-friendly/no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }],
|
||||
'prettier/prettier': ['error', {}, { usePrettierrc: true }],
|
||||
}
|
||||
|
||||
22
docs/src/.vuepress/auto-imports.d.ts
vendored
22
docs/src/.vuepress/auto-imports.d.ts
vendored
@@ -3,14 +3,17 @@
|
||||
declare global {
|
||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
||||
const biSyncRef: typeof import('@vueuse/core')['biSyncRef']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const computedAsync: typeof import('@vueuse/core')['computedAsync']
|
||||
const computedEager: typeof import('@vueuse/core')['computedEager']
|
||||
const computedInject: typeof import('@vueuse/core')['computedInject']
|
||||
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
|
||||
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
|
||||
const controlledRef: typeof import('@vueuse/core')['controlledRef']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createEventHook: typeof import('@vueuse/core')['createEventHook']
|
||||
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
|
||||
const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
|
||||
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
|
||||
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
|
||||
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
|
||||
@@ -31,6 +34,9 @@ declare global {
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const logicAnd: typeof import('@vueuse/core')['logicAnd']
|
||||
const logicNot: typeof import('@vueuse/core')['logicNot']
|
||||
const logicOr: typeof import('@vueuse/core')['logicOr']
|
||||
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
@@ -61,12 +67,17 @@ declare global {
|
||||
const reactivePick: typeof import('@vueuse/core')['reactivePick']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
|
||||
const refDebounced: typeof import('@vueuse/core')['refDebounced']
|
||||
const refDefault: typeof import('@vueuse/core')['refDefault']
|
||||
const refThrottled: typeof import('@vueuse/core')['refThrottled']
|
||||
const refWithControl: typeof import('@vueuse/core')['refWithControl']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const syncRef: typeof import('@vueuse/core')['syncRef']
|
||||
const syncRefs: typeof import('@vueuse/core')['syncRefs']
|
||||
const templateRef: typeof import('@vueuse/core')['templateRef']
|
||||
const throttledRef: typeof import('@vueuse/core')['throttledRef']
|
||||
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
|
||||
@@ -75,6 +86,7 @@ declare global {
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
|
||||
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
|
||||
@@ -102,6 +114,7 @@ declare global {
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useCycleList: typeof import('@vueuse/core')['useCycleList']
|
||||
const useDark: typeof import('@vueuse/core')['useDark']
|
||||
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
|
||||
const useDebounce: typeof import('@vueuse/core')['useDebounce']
|
||||
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
|
||||
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
|
||||
@@ -123,10 +136,12 @@ declare global {
|
||||
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
|
||||
const useFavicon: typeof import('@vueuse/core')['useFavicon']
|
||||
const useFetch: typeof import('@vueuse/core')['useFetch']
|
||||
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
|
||||
const useFocus: typeof import('@vueuse/core')['useFocus']
|
||||
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
|
||||
const useFps: typeof import('@vueuse/core')['useFps']
|
||||
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
||||
const useGamepad: typeof import('@vueuse/core')['useGamepad']
|
||||
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
|
||||
const useIdle: typeof import('@vueuse/core')['useIdle']
|
||||
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
|
||||
@@ -184,6 +199,7 @@ declare global {
|
||||
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
|
||||
const useTimeout: typeof import('@vueuse/core')['useTimeout']
|
||||
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
|
||||
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
|
||||
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
|
||||
const useTitle: typeof import('@vueuse/core')['useTitle']
|
||||
const useToggle: typeof import('@vueuse/core')['useToggle']
|
||||
@@ -204,8 +220,12 @@ declare global {
|
||||
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
|
||||
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
|
||||
const watchOnce: typeof import('@vueuse/core')['watchOnce']
|
||||
const watchPausable: typeof import('@vueuse/core')['watchPausable']
|
||||
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
|
||||
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
|
||||
const whenever: typeof import('@vueuse/core')['whenever']
|
||||
}
|
||||
|
||||
@@ -271,6 +271,52 @@ const elements = ref([
|
||||
</template>
|
||||
```
|
||||
|
||||
### Edge Template
|
||||
|
||||
You can also set a template per edge, which will overwrite the edge-type component but will retain
|
||||
the type otherwise.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<script setup>
|
||||
import { markRaw } from 'vue'
|
||||
import CustomEdge from './CustomEdge.vue'
|
||||
|
||||
const elements = ref([
|
||||
{
|
||||
id: '1',
|
||||
label: 'Node 1',
|
||||
position: { x: 0, y: 0 },
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: 'Node 2',
|
||||
position: { x: 0, y: 150 },
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: 'Node 3',
|
||||
position: { x: 0, y: 300 },
|
||||
},
|
||||
{
|
||||
id: 'e1-2',
|
||||
source: '1',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
id: 'e1-3',
|
||||
source: '1',
|
||||
target: '2',
|
||||
template: markRaw(CustomEdge),
|
||||
},
|
||||
])
|
||||
</script>
|
||||
<template>
|
||||
<div style="height: 300px">
|
||||
<VueFlow v-model="elements" />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Custom Edge Props
|
||||
|
||||
Your custom edges are wrapped so that the basic functions like selecting work.
|
||||
|
||||
@@ -266,6 +266,44 @@ const elements = ref([
|
||||
You can find a more advanced example <router-link to="/examples/custom-node/">here</router-link>.
|
||||
:::
|
||||
|
||||
### Node Template
|
||||
|
||||
You can also set a template per node, which will overwrite the node-type component but will retain
|
||||
the type otherwise.
|
||||
|
||||
```vue:no-line-numbers
|
||||
<script setup>
|
||||
import { markRaw } from 'vue'
|
||||
import CustomNode from './CustomNode.vue'
|
||||
import CustomNode from './OverwriteCustomNode.vue'
|
||||
import SpecialNode from './SpecialNode.vue'
|
||||
|
||||
const nodeTypes = {
|
||||
custom: markRaw(CustomNode),
|
||||
special: markRaw(SpecialNode),
|
||||
}
|
||||
|
||||
const elements = ref([
|
||||
{
|
||||
id: '1',
|
||||
label: 'Node 1',
|
||||
type: 'custom',
|
||||
template: markRaw(OverwriteCustomNode),
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: 'Node 1',
|
||||
type: 'special',
|
||||
}
|
||||
])
|
||||
</script>
|
||||
<template>
|
||||
<div style="height: 300px">
|
||||
<VueFlow v-model="elements" :node-types="nodeTypes" />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Custom Node Props
|
||||
|
||||
Your custom nodes are wrapped so that the basic functions like dragging or selecting work.
|
||||
|
||||
@@ -124,8 +124,9 @@ watch(
|
||||
)
|
||||
|
||||
const type = computed(() => {
|
||||
let edgeType = edge.value.template ?? store.getEdgeTypes[name.value]
|
||||
const instance = getCurrentInstance()
|
||||
let edgeType = store.getEdgeTypes[name.value]
|
||||
|
||||
if (typeof edgeType === 'string') {
|
||||
if (instance) {
|
||||
const components = Object.keys(instance.appContext.components)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { useDraggableCore } from '@braks/revue-draggable'
|
||||
import { CSSProperties } from 'vue'
|
||||
import { CSSProperties, isVNode } from 'vue'
|
||||
import { useVueFlow } from '../../composables'
|
||||
import { GraphNode, NodeComponent, SnapGrid } from '../../types'
|
||||
import { NodeId, Slots } from '../../context'
|
||||
@@ -89,8 +89,9 @@ watch(
|
||||
)
|
||||
|
||||
const type = computed(() => {
|
||||
let nodeType = node.value.template ?? store.getNodeTypes[name.value]
|
||||
const instance = getCurrentInstance()
|
||||
let nodeType = store.getNodeTypes[name.value]
|
||||
|
||||
if (typeof nodeType === 'string') {
|
||||
if (instance) {
|
||||
const components = Object.keys(instance.appContext.components)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CSSProperties } from 'vue'
|
||||
import { Component, CSSProperties, VNode } from 'vue'
|
||||
import { Position, Element, ElementData } from './flow'
|
||||
import { GraphNode } from './node'
|
||||
import { EdgeComponent, EdgeTextProps } from './components'
|
||||
|
||||
/** Edge markers */
|
||||
export enum MarkerType {
|
||||
@@ -42,6 +43,7 @@ export interface MarkerProps {
|
||||
export type EdgeMarkerType = string | MarkerType | EdgeMarker
|
||||
|
||||
export interface Edge<Data = ElementData> extends Element<Data> {
|
||||
label?: string | VNode | Component<EdgeTextProps>
|
||||
/** Source node id */
|
||||
source: string
|
||||
/** Target node id */
|
||||
@@ -74,6 +76,9 @@ export interface Edge<Data = ElementData> extends Element<Data> {
|
||||
updatable?: boolean
|
||||
/** Disable/enable selecting edge */
|
||||
selectable?: boolean
|
||||
|
||||
/** overwrites current edge type */
|
||||
template?: EdgeComponent
|
||||
}
|
||||
|
||||
export type DefaultEdgeOptions = Omit<
|
||||
@@ -101,12 +106,7 @@ export interface EdgeProps<Data = ElementData, SourceNodeData = any, TargetNodeD
|
||||
id: string
|
||||
sourceNode: GraphNode<SourceNodeData>
|
||||
targetNode: GraphNode<TargetNodeData>
|
||||
label?:
|
||||
| string
|
||||
| {
|
||||
props?: any
|
||||
component: any
|
||||
}
|
||||
label?: string | VNode
|
||||
type?: string
|
||||
data?: Data
|
||||
style?: CSSProperties
|
||||
@@ -139,12 +139,7 @@ export interface SmoothStepEdgeProps<Data = ElementData, SourceNodeData = any, T
|
||||
id: string
|
||||
sourceNode: GraphNode<SourceNodeData>
|
||||
targetNode: GraphNode<TargetNodeData>
|
||||
label?:
|
||||
| string
|
||||
| {
|
||||
props?: any
|
||||
component: any
|
||||
}
|
||||
label?: string | VNode
|
||||
type?: string
|
||||
data?: Data
|
||||
style?: CSSProperties
|
||||
@@ -159,8 +154,6 @@ export interface SmoothStepEdgeProps<Data = ElementData, SourceNodeData = any, T
|
||||
targetHandleId?: string
|
||||
source: string
|
||||
target: string
|
||||
sourceHandle?: string
|
||||
targetHandle?: string
|
||||
labelStyle?: any
|
||||
labelShowBg?: boolean
|
||||
labelBgStyle?: any
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CSSProperties, VNode } from 'vue'
|
||||
import { Component, CSSProperties, VNode } from 'vue'
|
||||
import { GraphEdge, Edge, DefaultEdgeOptions } from './edge'
|
||||
import { GraphNode, CoordinateExtent, Node } from './node'
|
||||
import { ConnectionLineType, ConnectionMode } from './connection'
|
||||
@@ -27,7 +27,7 @@ export type StyleFunc<Data = ElementData> = (element: FlowElement<Data>) => Styl
|
||||
/** base element props */
|
||||
export interface Element<Data extends ElementData = ElementData> {
|
||||
id: string
|
||||
label?: string | VNode
|
||||
label?: string | VNode | Component
|
||||
type?: string
|
||||
data?: Data
|
||||
class?: string | ClassFunc<Data>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { VNode } from 'vue'
|
||||
import { Component, VNode } from 'vue'
|
||||
import { XYPosition, Position, SnapGrid, Element, XYZPosition, Dimensions, ElementData } from './flow'
|
||||
import { DefaultNodeTypes } from './components'
|
||||
import { DefaultNodeTypes, NodeComponent } from './components'
|
||||
import { HandleElement, ValidConnectionFunc } from './handle'
|
||||
|
||||
/** Defined as [[x-from, y-from], [x-to, y-to]] **/
|
||||
@@ -55,6 +55,9 @@ export interface Node<Data = ElementData> extends Element<Data> {
|
||||
* or pass a string with units (height: `10rem` -> height: 10rem)
|
||||
*/
|
||||
height?: number | string | HeightFunc
|
||||
|
||||
/** overwrites current node type */
|
||||
template?: NodeComponent
|
||||
}
|
||||
|
||||
export interface GraphNode<Data = ElementData> extends Node<Data> {
|
||||
|
||||
Reference in New Issue
Block a user