refactor(core,edges): add div based edge label renderer
This commit is contained in:
23
packages/core/src/components/Edges/EdgeLabelRenderer.vue
Normal file
23
packages/core/src/components/Edges/EdgeLabelRenderer.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user