fix: nodes as fragments
feat: accept vnode as edge text
This commit is contained in:
@@ -1,4 +1,10 @@
|
|||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
interface CustomLabelProps {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<CustomLabelProps>()
|
||||||
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<tspan dy="10" x="0">I am a `tspan`</tspan>
|
<tspan dy="10" x="0">{{ props.text }}</tspan>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import CustomEdge from './CustomEdge.vue'
|
import CustomEdge from './CustomEdge.vue'
|
||||||
import CustomEdge2 from './CustomEdge2.vue'
|
import CustomEdge2 from './CustomEdge2.vue'
|
||||||
|
import CustomLabel from './CustomLabel.vue'
|
||||||
import Flow, {
|
import Flow, {
|
||||||
MiniMap,
|
MiniMap,
|
||||||
Controls,
|
Controls,
|
||||||
@@ -37,7 +38,12 @@ const initialElements = [
|
|||||||
id: 'e5-6',
|
id: 'e5-6',
|
||||||
source: '5',
|
source: '5',
|
||||||
target: '6',
|
target: '6',
|
||||||
label: 'foobar',
|
label: {
|
||||||
|
component: CustomLabel,
|
||||||
|
props: {
|
||||||
|
text: 'custom label text',
|
||||||
|
},
|
||||||
|
},
|
||||||
labelStyle: { fill: 'red', fontWeight: 700 },
|
labelStyle: { fill: 'red', fontWeight: 700 },
|
||||||
arrowHeadType: ArrowHeadType.Arrow,
|
arrowHeadType: ArrowHeadType.Arrow,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ const edgePos = computed(() =>
|
|||||||
v-if="!props.edge.isHidden && isVisible(edgePos)"
|
v-if="!props.edge.isHidden && isVisible(edgePos)"
|
||||||
:class="[
|
:class="[
|
||||||
'revue-flow__edge',
|
'revue-flow__edge',
|
||||||
`revue-flow__edge-${props.type.name || 'default'}`,
|
`revue-flow__edge-${props.edge.type || 'default'}`,
|
||||||
{
|
{
|
||||||
selected: isSelected,
|
selected: isSelected,
|
||||||
animated: props.edge.animated,
|
animated: props.edge.animated,
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import { HTMLAttributes, VNode } from 'vue'
|
|||||||
interface EdgeTextProps extends HTMLAttributes {
|
interface EdgeTextProps extends HTMLAttributes {
|
||||||
x: number
|
x: number
|
||||||
y: number
|
y: number
|
||||||
label?: string | VNode
|
label?:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
component: VNode
|
||||||
|
props?: any
|
||||||
|
}
|
||||||
labelStyle?: any
|
labelStyle?: any
|
||||||
labelShowBg?: boolean
|
labelShowBg?: boolean
|
||||||
labelBgStyle?: any
|
labelBgStyle?: any
|
||||||
@@ -38,7 +43,11 @@ const { width = 0, height = 0, x = 0, y = 0 } = useElementBounding(edgeRef)
|
|||||||
:ry="props.labelBgBorderRadius"
|
:ry="props.labelBgBorderRadius"
|
||||||
/>
|
/>
|
||||||
<text ref="edge-text" class="revue-flow__edge-text" :y="height / 2" dy="0.3em" :style="props.labelStyle">
|
<text ref="edge-text" class="revue-flow__edge-text" :y="height / 2" dy="0.3em" :style="props.labelStyle">
|
||||||
<component :is="props.label" v-if="typeof props.label !== 'string'" />
|
<component
|
||||||
|
:is="props.label.component"
|
||||||
|
v-if="typeof props.label.component !== 'undefined'"
|
||||||
|
v-bind="{ ...props, ...props.label.props, width, height, x, y }"
|
||||||
|
/>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ props.label }}
|
{{ props.label }}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -17,12 +17,10 @@ const props = withDefaults(defineProps<DefaultNodeProps>(), {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="revue-flow__node-default">
|
<Handle type="target" :position="props.targetPosition" :is-connectable="props.connectable" />
|
||||||
<Handle type="target" :position="props.targetPosition" :is-connectable="props.connectable" />
|
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
||||||
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
<template v-else>
|
||||||
<template v-else>
|
{{ props.data?.label }}
|
||||||
{{ props.data?.label }}
|
</template>
|
||||||
</template>
|
<Handle type="source" :position="props.sourcePosition" :is-connectable="props.connectable" />
|
||||||
<Handle type="source" :position="props.sourcePosition" :is-connectable="props.connectable" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,11 +15,9 @@ const props = withDefaults(defineProps<InputNodeProps>(), {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="revue-flow__node-input">
|
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
||||||
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
<template v-else>
|
||||||
<template v-else>
|
{{ props.data?.label }}
|
||||||
{{ props.data?.label }}
|
</template>
|
||||||
</template>
|
<Handle type="source" :position="props.sourcePosition" :connectable="props.connectable" />
|
||||||
<Handle type="source" :position="props.sourcePosition" :connectable="props.connectable" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,11 +15,9 @@ const props = withDefaults(defineProps<OutputNodeProps>(), {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="revue-flow__node-output">
|
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
||||||
<component :is="props.data?.label" v-if="typeof props.data?.label !== 'string'" />
|
<template v-else>
|
||||||
<template v-else>
|
{{ props.data?.label }}
|
||||||
{{ props.data?.label }}
|
</template>
|
||||||
</template>
|
<Handle type="source" :position="props.targetPosition" :is-connectable="props.connectable" />
|
||||||
<Handle type="source" :position="props.targetPosition" :is-connectable="props.connectable" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -114,19 +114,19 @@ const defaultEdgeTypes: Record<string, EdgeType> = {
|
|||||||
const store = useStore(props)
|
const store = useStore(props)
|
||||||
const hooks = useHooks(emit)
|
const hooks = useHooks(emit)
|
||||||
|
|
||||||
const init = () => {
|
const init = (opts: typeof props) => {
|
||||||
store.$state = { ...store.$state, ...props }
|
store.$state = { ...store.$state, ...opts }
|
||||||
store.setElements(props.elements)
|
store.setElements(opts.elements)
|
||||||
store.setMinZoom(props.minZoom)
|
store.setMinZoom(opts.minZoom)
|
||||||
store.setMaxZoom(props.maxZoom)
|
store.setMaxZoom(opts.maxZoom)
|
||||||
store.setTranslateExtent(props.translateExtent)
|
store.setTranslateExtent(opts.translateExtent)
|
||||||
store.setNodeExtent(props.nodeExtent)
|
store.setNodeExtent(opts.nodeExtent)
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeUnmount(() => store?.$dispose())
|
onBeforeUnmount(() => store?.$dispose())
|
||||||
|
|
||||||
onUpdated(() => init())
|
watch(props, (val) => init(val))
|
||||||
init()
|
init(props)
|
||||||
|
|
||||||
const nodeTypes = createNodeTypes({ ...defaultNodeTypes, ...props.nodeTypes })
|
const nodeTypes = createNodeTypes({ ...defaultNodeTypes, ...props.nodeTypes })
|
||||||
const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
|
const edgeTypes = createEdgeTypes({ ...defaultEdgeTypes, ...props.edgeTypes })
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ const type = (node: TNode) => {
|
|||||||
}
|
}
|
||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = (nodeId: string) => store.selectedElements?.some(({ id }) => id === nodeId)
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
@@ -52,7 +50,7 @@ const selected = (nodeId: string) => store.selectedElements?.some(({ id }) => id
|
|||||||
:type="type(node)"
|
:type="type(node)"
|
||||||
:scale="store.transform[2]"
|
:scale="store.transform[2]"
|
||||||
:snap-grid="store.snapToGrid ? store.snapGrid : undefined"
|
:snap-grid="store.snapToGrid ? store.snapGrid : undefined"
|
||||||
:selected="selected(node.id)"
|
:selected="store.selectedElements?.some(({ id }) => id === node.id)"
|
||||||
:selectable="node.selectable || store.elementsSelectable"
|
:selectable="node.selectable || store.elementsSelectable"
|
||||||
:connectable="node.connectable || store.nodesConnectable"
|
:connectable="node.connectable || store.nodesConnectable"
|
||||||
:draggable="node.draggable || store.nodesDraggable"
|
:draggable="node.draggable || store.nodesDraggable"
|
||||||
|
|||||||
Reference in New Issue
Block a user