Md Afiq Iskandar 8919ac819c Add Interactive Edges and Edge Configuration to Process Flow
- Introduced new components: ArrowEdge, CustomEdge, InteractiveArrowEdge, and EdgeConfiguration for enhanced edge management in the process flow.
- Implemented dynamic edge paths with customizable styles, labels, and animations, improving visual representation and user interaction.
- Enhanced ProcessFlowCanvas to support new edge types and configurations, allowing for more flexible process designs.
- Updated ProcessFlowNodes to include new edge components, ensuring seamless integration with existing node functionalities.
- Improved user experience by providing configuration options for edges, including animation and style settings, directly within the process builder.
2025-07-11 14:13:42 +08:00

140 lines
2.6 KiB
Vue

<script setup>
import { BaseEdge, EdgeLabelRenderer, getSmoothStepPath } from '@vue-flow/core'
import { computed } from 'vue'
const props = defineProps({
sourceX: {
type: Number,
required: true,
},
sourceY: {
type: Number,
required: true,
},
targetX: {
type: Number,
required: true,
},
targetY: {
type: Number,
required: true,
},
sourcePosition: {
type: String,
required: true,
},
targetPosition: {
type: String,
required: true,
},
selected: {
type: Boolean,
default: false,
},
animated: {
type: Boolean,
default: false,
},
label: {
type: String,
default: '',
},
style: {
type: Object,
default: () => ({}),
},
markerEnd: {
type: String,
default: '',
},
data: {
type: Object,
default: () => ({}),
}
})
const path = computed(() => {
const [edgePath, labelX, labelY] = getSmoothStepPath({
sourceX: props.sourceX,
sourceY: props.sourceY,
sourcePosition: props.sourcePosition,
targetX: props.targetX,
targetY: props.targetY,
targetPosition: props.targetPosition,
borderRadius: 8,
offset: 20
})
return {
path: edgePath,
labelX,
labelY
}
})
const edgeStyle = computed(() => ({
stroke: props.selected ? '#ff6b6b' : '#555',
strokeWidth: props.selected ? 3 : 2,
strokeDasharray: props.animated ? '5,5' : 'none',
...props.style
}))
const markerEndUrl = computed(() => {
return props.selected ? 'url(#arrow-selected)' : 'url(#arrow)'
})
</script>
<script>
export default {
inheritAttrs: false,
}
</script>
<template>
<!-- Main edge path -->
<BaseEdge
:path="path.path"
:style="edgeStyle"
:marker-end="markerEndUrl"
:class="{
'animated': animated,
'selected': selected
}"
/>
<!-- Edge label if provided -->
<EdgeLabelRenderer v-if="label">
<div
:style="{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${path.labelX}px, ${path.labelY}px)`,
pointerEvents: 'all',
fontSize: '11px',
fontWeight: '600',
background: 'white',
padding: '3px 8px',
borderRadius: '12px',
border: '1.5px solid #3b82f6',
boxShadow: '0 2px 8px rgba(59, 130, 246, 0.2)',
color: '#1e40af',
whiteSpace: 'nowrap',
zIndex: 10
}"
class="edge-label nodrag nopan"
>
{{ label }}
</div>
</EdgeLabelRenderer>
</template>
<style scoped>
.animated {
animation: dash 2s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: -10;
}
}
</style>