refactor(core,edges): add div based edge label renderer
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@vue-flow/core': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Teleport edge labels into separate svg container (fixes edges overlapping edge labels)
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { useVueFlow } from '../../composables'
|
||||||
|
|
||||||
|
const { viewportRef } = useVueFlow()
|
||||||
|
|
||||||
|
const teleportTarget = $computed(() => viewportRef.value?.getElementsByClassName('vue-flow__edge-labels')[0])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'EdgeLabelRenderer',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<svg>
|
||||||
|
<foreignObject height="0" width="0">
|
||||||
|
<Teleport :to="teleportTarget" :disabled="!teleportTarget">
|
||||||
|
<slot />
|
||||||
|
</Teleport>
|
||||||
|
</foreignObject>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { isString } from '@vueuse/core'
|
||||||
import type { EdgeTextProps } from '../../types/components'
|
import type { EdgeTextProps } from '../../types/components'
|
||||||
import type { Rect as RectType } from '../../types'
|
import type { Rect as RectType } from '../../types'
|
||||||
|
|
||||||
@@ -55,10 +56,8 @@ export default {
|
|||||||
/>
|
/>
|
||||||
<text v-bind="$attrs" ref="el" class="vue-flow__edge-text" :y="box.height / 2" dy="0.3em" :style="labelStyle">
|
<text v-bind="$attrs" ref="el" class="vue-flow__edge-text" :y="box.height / 2" dy="0.3em" :style="labelStyle">
|
||||||
<slot>
|
<slot>
|
||||||
<component :is="label" v-if="typeof label !== 'string' && typeof label" />
|
<component :is="label" v-if="!isString(label)" />
|
||||||
<template v-else>
|
<template v-else> {{ label }} </template>
|
||||||
{{ label }}
|
|
||||||
</template>
|
|
||||||
</slot>
|
</slot>
|
||||||
</text>
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ export { default as StraightEdge } from './StraightEdge'
|
|||||||
export { default as EdgeAnchor } from './EdgeAnchor'
|
export { default as EdgeAnchor } from './EdgeAnchor'
|
||||||
export { default as EdgeText } from './EdgeText.vue'
|
export { default as EdgeText } from './EdgeText.vue'
|
||||||
export { default as EdgeWrapper } from './Wrapper'
|
export { default as EdgeWrapper } from './Wrapper'
|
||||||
|
export { default as EdgeLabelRenderer } from './EdgeLabelRenderer.vue'
|
||||||
|
|||||||
@@ -127,24 +127,27 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<svg v-for="group of groups" :key="group.level" class="vue-flow__edges vue-flow__container" :style="`z-index: ${group.level}`">
|
<template v-for="group of groups" :key="group.level">
|
||||||
<MarkerDefinitions v-if="group.isMaxLevel" />
|
<svg class="vue-flow__edges vue-flow__container" :style="`z-index: ${group.level}`">
|
||||||
<g>
|
<MarkerDefinitions v-if="group.isMaxLevel" />
|
||||||
<EdgeWrapper
|
<g>
|
||||||
v-for="edge of group.edges"
|
<EdgeWrapper
|
||||||
:id="edge.id"
|
v-for="edge of group.edges"
|
||||||
:key="edge.id"
|
:id="edge.id"
|
||||||
:edge="edge"
|
:key="edge.id"
|
||||||
:type="getType(edge.type, edge.template)"
|
:edge="edge"
|
||||||
:name="edge.type || 'default'"
|
:type="getType(edge.type, edge.template)"
|
||||||
:source-node="getNode(edge.source)"
|
:name="edge.type || 'default'"
|
||||||
:target-node="getNode(edge.target)"
|
:source-node="getNode(edge.source)"
|
||||||
:selectable="selectable(edge.selectable)"
|
:target-node="getNode(edge.target)"
|
||||||
:updatable="updatable(edge.updatable)"
|
:selectable="selectable(edge.selectable)"
|
||||||
:class="getClass(edge)"
|
:updatable="updatable(edge.updatable)"
|
||||||
/>
|
:class="getClass(edge)"
|
||||||
</g>
|
/>
|
||||||
</svg>
|
</g>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
<svg v-if="connectionLineVisible && !!sourceNode" class="vue-flow__edges vue-flow__connectionline vue-flow__container">
|
<svg v-if="connectionLineVisible && !!sourceNode" class="vue-flow__edges vue-flow__connectionline vue-flow__container">
|
||||||
<ConnectionLine :source-node="sourceNode" />
|
<ConnectionLine :source-node="sourceNode" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ export default {
|
|||||||
:style="{ transform: `translate(${viewport.x}px,${viewport.y}px) scale(${viewport.zoom})`, opacity: ready ? undefined : 0 }"
|
:style="{ transform: `translate(${viewport.x}px,${viewport.y}px) scale(${viewport.zoom})`, opacity: ready ? undefined : 0 }"
|
||||||
>
|
>
|
||||||
<EdgeRenderer />
|
<EdgeRenderer />
|
||||||
|
|
||||||
|
<div class="vue-flow__edge-labels" />
|
||||||
|
|
||||||
<NodeRenderer />
|
<NodeRenderer />
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,16 @@ export { default as VueFlow } from './container/VueFlow/VueFlow.vue'
|
|||||||
|
|
||||||
export { default as Handle } from './components/Handle/Handle.vue'
|
export { default as Handle } from './components/Handle/Handle.vue'
|
||||||
|
|
||||||
export { StraightEdge, StepEdge, BezierEdge, SimpleBezierEdge, SmoothStepEdge, BaseEdge, EdgeText } from './components/Edges'
|
export {
|
||||||
|
StraightEdge,
|
||||||
|
StepEdge,
|
||||||
|
BezierEdge,
|
||||||
|
SimpleBezierEdge,
|
||||||
|
SmoothStepEdge,
|
||||||
|
BaseEdge,
|
||||||
|
EdgeText,
|
||||||
|
EdgeLabelRenderer,
|
||||||
|
} from './components/Edges'
|
||||||
|
|
||||||
export { getBezierPath, getSimpleBezierPath, getSmoothStepPath, getStraightPath } from './components/Edges/utils'
|
export { getBezierPath, getSimpleBezierPath, getSmoothStepPath, getStraightPath } from './components/Edges/utils'
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,13 @@
|
|||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vue-flow__edge-labels {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.vue-flow__nodesselection-rect:focus,
|
.vue-flow__nodesselection-rect:focus,
|
||||||
.vue-flow__nodesselection-rect:focus-visible {
|
.vue-flow__nodesselection-rect:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export const parseEdge = (edge: Edge, defaults?: Partial<GraphEdge>): GraphEdge
|
|||||||
selectable: edge.selectable,
|
selectable: edge.selectable,
|
||||||
data: shallowReactive(edge.data || {}),
|
data: shallowReactive(edge.data || {}),
|
||||||
events: shallowReactive(edge.events || {}),
|
events: shallowReactive(edge.events || {}),
|
||||||
label: edge.label && !isString(edge.label) ? markRaw(edge.label) : undefined,
|
label: edge.label && !isString(edge.label) ? markRaw(edge.label) : edge.label,
|
||||||
...defaults,
|
...defaults,
|
||||||
} as GraphEdge)
|
} as GraphEdge)
|
||||||
: defaults
|
: defaults
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
|
|
||||||
&.dragging {
|
&.dragging {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__transformationpane {
|
.vue-flow__transformationpane {
|
||||||
@@ -36,6 +36,13 @@
|
|||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vue-flow__edge-labels {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.vue-flow__nodesselection-rect:focus,
|
.vue-flow__nodesselection-rect:focus,
|
||||||
.vue-flow__nodesselection-rect:focus-visible {
|
.vue-flow__nodesselection-rect:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -57,48 +64,48 @@
|
|||||||
pointer-events: visibleStroke;
|
pointer-events: visibleStroke;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.animated path {
|
&.animated path {
|
||||||
stroke-dasharray: 5;
|
stroke-dasharray: 5;
|
||||||
animation: dashdraw 0.5s linear infinite;
|
animation: dashdraw 0.5s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.inactive {
|
&.inactive {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected,
|
&.selected,
|
||||||
&:focus,
|
&:focus,
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected .vue-flow__edge-path,
|
&.selected .vue-flow__edge-path,
|
||||||
&:focus .vue-flow__edge-path,
|
&:focus .vue-flow__edge-path,
|
||||||
&:focus-visible .vue-flow__edge-path {
|
&:focus-visible .vue-flow__edge-path {
|
||||||
stroke: #555;
|
stroke: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-textwrapper {
|
&-textwrapper {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-textbg {
|
&-textbg {
|
||||||
fill: white;
|
fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__edge-text {
|
&-text {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__connection {
|
.vue-flow__connection {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&.animated {
|
&.animated {
|
||||||
stroke-dasharray: 5;
|
stroke-dasharray: 5;
|
||||||
animation: dashdraw 0.5s linear infinite;
|
animation: dashdraw 0.5s linear infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__connectionline {
|
.vue-flow__connectionline {
|
||||||
@@ -118,9 +125,9 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
|
|
||||||
&.dragging {
|
&.dragging {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__nodesselection {
|
.vue-flow__nodesselection {
|
||||||
@@ -128,11 +135,15 @@
|
|||||||
transform-origin: left top;
|
transform-origin: left top;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&-rect {
|
&-rect {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
|
||||||
|
&.dragging {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__handle {
|
.vue-flow__handle {
|
||||||
@@ -141,35 +152,35 @@
|
|||||||
min-width: 5px;
|
min-width: 5px;
|
||||||
min-height: 5px;
|
min-height: 5px;
|
||||||
|
|
||||||
&.connectable {
|
&.connectable {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-bottom {
|
&-bottom {
|
||||||
top: auto;
|
top: auto;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: -4px;
|
bottom: -4px;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-top {
|
&-top {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: -4px;
|
top: -4px;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-left {
|
&-left {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: -4px;
|
left: -4px;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-right {
|
&-right {
|
||||||
right: -4px;
|
right: -4px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vue-flow__edgeupdater {
|
.vue-flow__edgeupdater {
|
||||||
@@ -182,26 +193,26 @@
|
|||||||
z-index: 5;
|
z-index: 5;
|
||||||
margin: 15px;
|
margin: 15px;
|
||||||
|
|
||||||
&.top {
|
&.top {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bottom {
|
&.bottom {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left {
|
&.left {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.center {
|
&.center {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes dashdraw {
|
@keyframes dashdraw {
|
||||||
|
|||||||
Reference in New Issue
Block a user