refactor(core,edges): add div based edge label renderer

This commit is contained in:
braks
2022-10-18 23:26:52 +02:00
committed by Braks
parent 0f2bc10fd2
commit 43ff2a42e6
10 changed files with 168 additions and 107 deletions

View File

@@ -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>

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup>
import { isString } from '@vueuse/core'
import type { EdgeTextProps } from '../../types/components'
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">
<slot>
<component :is="label" v-if="typeof label !== 'string' && typeof label" />
<template v-else>
{{ label }}
</template>
<component :is="label" v-if="!isString(label)" />
<template v-else> {{ label }} </template>
</slot>
</text>
</g>

View File

@@ -7,3 +7,4 @@ export { default as StraightEdge } from './StraightEdge'
export { default as EdgeAnchor } from './EdgeAnchor'
export { default as EdgeText } from './EdgeText.vue'
export { default as EdgeWrapper } from './Wrapper'
export { default as EdgeLabelRenderer } from './EdgeLabelRenderer.vue'

View File

@@ -127,24 +127,27 @@ export default {
</script>
<template>
<svg v-for="group of groups" :key="group.level" class="vue-flow__edges vue-flow__container" :style="`z-index: ${group.level}`">
<MarkerDefinitions v-if="group.isMaxLevel" />
<g>
<EdgeWrapper
v-for="edge of group.edges"
:id="edge.id"
:key="edge.id"
:edge="edge"
:type="getType(edge.type, edge.template)"
:name="edge.type || 'default'"
:source-node="getNode(edge.source)"
:target-node="getNode(edge.target)"
:selectable="selectable(edge.selectable)"
:updatable="updatable(edge.updatable)"
:class="getClass(edge)"
/>
</g>
</svg>
<template v-for="group of groups" :key="group.level">
<svg class="vue-flow__edges vue-flow__container" :style="`z-index: ${group.level}`">
<MarkerDefinitions v-if="group.isMaxLevel" />
<g>
<EdgeWrapper
v-for="edge of group.edges"
:id="edge.id"
:key="edge.id"
:edge="edge"
:type="getType(edge.type, edge.template)"
:name="edge.type || 'default'"
:source-node="getNode(edge.source)"
:target-node="getNode(edge.target)"
:selectable="selectable(edge.selectable)"
:updatable="updatable(edge.updatable)"
:class="getClass(edge)"
/>
</g>
</svg>
</template>
<svg v-if="connectionLineVisible && !!sourceNode" class="vue-flow__edges vue-flow__connectionline vue-flow__container">
<ConnectionLine :source-node="sourceNode" />
</svg>

View File

@@ -53,6 +53,9 @@ export default {
:style="{ transform: `translate(${viewport.x}px,${viewport.y}px) scale(${viewport.zoom})`, opacity: ready ? undefined : 0 }"
>
<EdgeRenderer />
<div class="vue-flow__edge-labels" />
<NodeRenderer />
<slot />
</div>

View File

@@ -7,7 +7,16 @@ export { default as VueFlow } from './container/VueFlow/VueFlow.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'

View File

@@ -39,6 +39,13 @@
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-visible {
outline: none;

View File

@@ -106,7 +106,7 @@ export const parseEdge = (edge: Edge, defaults?: Partial<GraphEdge>): GraphEdge
selectable: edge.selectable,
data: shallowReactive(edge.data || {}),
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,
} as GraphEdge)
: defaults

View File

@@ -17,9 +17,9 @@
z-index: 1;
cursor: grab;
&.dragging {
cursor: grabbing;
}
&.dragging {
cursor: grabbing;
}
}
.vue-flow__transformationpane {
@@ -36,6 +36,13 @@
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-visible {
outline: none;
@@ -57,48 +64,48 @@
pointer-events: visibleStroke;
cursor: pointer;
&.animated path {
stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite;
}
&.animated path {
stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite;
}
&.inactive {
pointer-events: none;
}
&.inactive {
pointer-events: none;
}
&.selected,
&:focus,
&:focus-visible {
outline: none;
}
&.selected,
&:focus,
&:focus-visible {
outline: none;
}
&.selected .vue-flow__edge-path,
&:focus .vue-flow__edge-path,
&:focus-visible .vue-flow__edge-path {
stroke: #555;
}
&.selected .vue-flow__edge-path,
&:focus .vue-flow__edge-path,
&:focus-visible .vue-flow__edge-path {
stroke: #555;
}
&-textwrapper {
pointer-events: all;
}
&-textwrapper {
pointer-events: all;
}
&-textbg {
fill: white;
}
&-textbg {
fill: white;
}
.vue-flow__edge-text {
pointer-events: none;
user-select: none;
}
&-text {
pointer-events: none;
user-select: none;
}
}
.vue-flow__connection {
pointer-events: none;
&.animated {
stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite;
}
&.animated {
stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite;
}
}
.vue-flow__connectionline {
@@ -118,9 +125,9 @@
box-sizing: border-box;
cursor: grab;
&.dragging {
cursor: grabbing;
}
&.dragging {
cursor: grabbing;
}
}
.vue-flow__nodesselection {
@@ -128,11 +135,15 @@
transform-origin: left top;
pointer-events: none;
&-rect {
position: absolute;
pointer-events: all;
cursor: grab;
}
&-rect {
position: absolute;
pointer-events: all;
cursor: grab;
&.dragging {
cursor: grabbing;
}
}
}
.vue-flow__handle {
@@ -141,35 +152,35 @@
min-width: 5px;
min-height: 5px;
&.connectable {
pointer-events: all;
cursor: crosshair;
}
&.connectable {
pointer-events: all;
cursor: crosshair;
}
&-bottom {
top: auto;
left: 50%;
bottom: -4px;
transform: translate(-50%, 0);
}
&-bottom {
top: auto;
left: 50%;
bottom: -4px;
transform: translate(-50%, 0);
}
&-top {
left: 50%;
top: -4px;
transform: translate(-50%, 0);
}
&-top {
left: 50%;
top: -4px;
transform: translate(-50%, 0);
}
&-left {
top: 50%;
left: -4px;
transform: translate(0, -50%);
}
&-left {
top: 50%;
left: -4px;
transform: translate(0, -50%);
}
&-right {
right: -4px;
top: 50%;
transform: translate(0, -50%);
}
&-right {
right: -4px;
top: 50%;
transform: translate(0, -50%);
}
}
.vue-flow__edgeupdater {
@@ -182,26 +193,26 @@
z-index: 5;
margin: 15px;
&.top {
top: 0;
}
&.top {
top: 0;
}
&.bottom {
bottom: 0;
}
&.bottom {
bottom: 0;
}
&.left {
left: 0;
}
&.left {
left: 0;
}
&.right {
right: 0;
}
&.right {
right: 0;
}
&.center {
left: 50%;
transform: translateX(-50%);
}
&.center {
left: 50%;
transform: translateX(-50%);
}
}
@keyframes dashdraw {