fix: render snake vs flow edge animations correctly

edges/index.tsx was never committed — both animation modes were
rendering as snake (truthy string check). Now uses animMode to
distinguish 'snake' (moving blob) from 'flow' (continuous flowing dashes).
This commit is contained in:
Pouzor
2026-03-29 15:18:19 +02:00
parent f9c8e37de3
commit e4c0d820f4
2 changed files with 27 additions and 21 deletions
+26 -20
View File
@@ -50,42 +50,48 @@ export function HomelableEdge({ id, source, target, sourceX, sourceY, targetX, t
...(selected ? { stroke: theme.colors.edgeSelectedColor, filter: `drop-shadow(0 0 4px ${theme.colors.edgeSelectedColor}88)` } : {}),
}
// Animated dot: slightly brighter + thicker than the base edge, travels source→target
const dotColor = customColor ?? (edgeType === 'vlan' ? getVlanColor(data?.vlan_id as number | undefined) : edgeColors[edgeType as keyof typeof edgeColors] as string)
const dotWidth = ((style.strokeWidth as number ?? 2) + 1.5) * 2
// Normalize animated value — supports legacy boolean (true → 'snake')
const animMode: 'none' | 'snake' | 'flow' =
data?.animated === true || data?.animated === 'snake' ? 'snake' :
data?.animated === 'flow' ? 'flow' : 'none'
const animColor = customColor ?? (edgeType === 'vlan' ? getVlanColor(data?.vlan_id as number | undefined) : edgeColors[edgeType as keyof typeof edgeColors] as string)
return (
<>
<BaseEdge id={id} path={edgePath} style={style} />
{data?.animated && (
{animMode === 'snake' && (
<path
d={edgePath}
fill="none"
stroke={dotColor}
strokeWidth={dotWidth}
stroke={animColor}
strokeWidth={((style.strokeWidth as number ?? 2) + 1.5) * 2}
strokeDasharray="20 10000"
strokeLinecap="round"
style={{ pointerEvents: 'none' }}
>
{isBidirectional ? (
<animate
attributeName="stroke-dashoffset"
values="-10000;0;-10000"
keyTimes="0;0.5;1"
dur="20s"
repeatCount="indefinite"
/>
<animate attributeName="stroke-dashoffset" values="-10000;0;-10000" keyTimes="0;0.5;1" dur="20s" repeatCount="indefinite" />
) : (
<animate
attributeName="stroke-dashoffset"
from="-10000"
to="0"
dur="10s"
repeatCount="indefinite"
/>
<animate attributeName="stroke-dashoffset" from="-10000" to="0" dur="10s" repeatCount="indefinite" />
)}
</path>
)}
{animMode === 'flow' && (
<path
d={edgePath}
fill="none"
stroke={animColor}
strokeWidth={Math.max(3, (style.strokeWidth as number ?? 2) * 1.8)}
strokeDasharray="6 12"
strokeLinecap="round"
strokeOpacity={0.85}
style={{ pointerEvents: 'none' }}
>
<animate attributeName="stroke-dashoffset" from="0" to="18" dur="1.2s" repeatCount="indefinite" />
</path>
)}
{data?.label && (
<EdgeLabelRenderer>
<div
+1 -1
View File
@@ -41,7 +41,7 @@ export interface ApiEdge {
speed?: string | null
custom_color?: string | null
path_style?: string | null
animated?: boolean
animated?: boolean | 'snake' | 'flow' | 'none'
source_handle?: string | null
target_handle?: string | null
}