Skip to content

Custom Edge Types

yh-flow supports registering and using custom edge types. Through a simple registration mechanism, you can configure unique appearances and interaction logics for specific types of edges without repeating code in every canvas.

Core Concepts

When using custom components, it is recommended to inject them via the yh-flow Props. This aligns with low coupling and high cohesion functional programming principles, and is fully compatible with SSR environments like Nuxt.

Inject component types via the edge-types property. This approach has a clear scope and does not pollute the global state, making it ideal for large-scale applications.

vue
<script setup lang="ts">
import { ref, defineComponent, h } from 'vue'
import { Flow } from '@yh-ui/flow'

// 1. Define or import your custom edge component
const MyCustomEdge = defineComponent({
  props: ['path', 'stroke'],
  setup(props) {
    return () => h('path', { d: props.path, stroke: 'orange', strokeWidth: 3, fill: 'none' })
  }
})

// 2. Map component to a specific type key
const edgeTypes = {
  'custom-orange': MyCustomEdge
}

const edges = ref([{ id: 'e1', source: 'a', target: 'b', type: 'custom-orange' }])
</script>

<template>
  <yh-flow :edges="edges" :edge-types="edgeTypes" />
</template>

2. Global Registration (Multi-Instance Sharing)

Use registerCustomEdge if you need to share the same custom styles across multiple independent flow instances. This adds the component to the internal global registry.

CAUTION

In SSR (Nuxt 3) environments, please register only in client-side plugins or prioritize Prop injection to prevent state leaks between requests.

typescript
import { registerCustomEdge } from '@yh-ui/flow'
// Import your component from a separate file
import MyEdgeComponent from './MyEdge.vue'

registerCustomEdge({
  type: 'my-custom-edge',
  component: MyEdgeComponent,
  label: 'Corporate Review Edge'
})

3. Slot Mode (Manual)

If you only want to change edge styles temporarily in a specific canvas or need access to complex parent context, use the #edge slot:

vue
<yh-flow :nodes="nodes" :edges="edges">
  <template #edge="edgeProps">
    <!-- Manual control over rendering -->
    <MySpecialEdge v-bind="edgeProps" />
  </template>
</yh-flow>

Complete Example

Developing a Custom Edge Component

Custom components receive a complete Prop object including coordinates, paths, center points, and original data.

vue
<!-- CustomEdgeComponent.vue -->
<template>
  <g class="custom-edge" :class="{ 'is-selected': edge.selected }">
    <!-- Main path -->
    <path
      :d="path"
      :stroke="stroke"
      :stroke-width="strokeWidth"
      fill="none"
      :stroke-dasharray="edge.animated ? '5,5' : 'none'"
    />

    <!-- Marker at the center -->
    <circle :cx="labelX" :cy="labelY" r="5" fill="#10b981" />

    <!-- Label -->
    <text v-if="edge.label" :x="labelX" :y="labelY - 10" text-anchor="middle" class="edge-label">
      {{ edge.label }}
    </text>
  </g>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import type { Edge } from '@yh-ui/flow'

interface Props {
  edge: Edge
  path: string
  sourceX: number
  sourceY: number
  targetX: number
  targetY: number
  labelX: number
  labelY: number
  stroke: string
  strokeWidth: number
}

const props = defineProps<Props>()
</script>

<style scoped>
.custom-edge path {
  transition: all 0.3s;
}
.custom-edge.is-selected path {
  stroke-width: 5;
  filter: drop-shadow(0 0 4px rgba(16, 185, 129, 0.5));
}
.edge-label {
  font-size: 12px;
  fill: #64748b;
  font-weight: bold;
}
</style>

Automatic Rendering Demo

The example below shows how the EdgeRenderer takes over rendering once a type is registered.

STREAMING
FINALIZING
Source
Transform
Archive
Automatic Rendering Demo

API Reference

Registration Functions

FunctionDescription
registerCustomEdge(edge: CustomEdge)Register global custom edge component
getCustomEdge(type: string)Get registered component information
registerEdgeTemplate(template: EdgeTemplate)Register edge template with defaults

Type Definitions

typescript
// Custom Edge Configuration
interface CustomEdge {
  type: string // Unique identifier for Edge.type
  component: Component // Vue component
  label?: string // Alias or description
}

// Props passed to custom components
interface EdgeProps {
  edge: Edge // Raw edge data
  path: string // Pre-calculated SVG path string
  sourceX: number // Source X
  sourceY: number // Source Y
  targetX: number // Target X
  targetY: number // Target Y
  labelX: number // Center point X
  labelY: number // Center point Y
  labelWidth: number // Pre-calculated label width (px)
  stroke: string // Pre-calculated stroke color
  strokeWidth: number // Calculated stroke width
}

Custom edge components must return valid SVG elements (typically wrapped in a <g> tag), otherwise rendering may break when layered.

Released under the MIT License.