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)` } : {}), ...(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 // Normalize animated value — supports legacy boolean (true → 'snake')
const dotColor = customColor ?? (edgeType === 'vlan' ? getVlanColor(data?.vlan_id as number | undefined) : edgeColors[edgeType as keyof typeof edgeColors] as string) const animMode: 'none' | 'snake' | 'flow' =
const dotWidth = ((style.strokeWidth as number ?? 2) + 1.5) * 2 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 ( return (
<> <>
<BaseEdge id={id} path={edgePath} style={style} /> <BaseEdge id={id} path={edgePath} style={style} />
{data?.animated && ( {animMode === 'snake' && (
<path <path
d={edgePath} d={edgePath}
fill="none" fill="none"
stroke={dotColor} stroke={animColor}
strokeWidth={dotWidth} strokeWidth={((style.strokeWidth as number ?? 2) + 1.5) * 2}
strokeDasharray="20 10000" strokeDasharray="20 10000"
strokeLinecap="round" strokeLinecap="round"
style={{ pointerEvents: 'none' }} style={{ pointerEvents: 'none' }}
> >
{isBidirectional ? ( {isBidirectional ? (
<animate <animate attributeName="stroke-dashoffset" values="-10000;0;-10000" keyTimes="0;0.5;1" dur="20s" repeatCount="indefinite" />
attributeName="stroke-dashoffset"
values="-10000;0;-10000"
keyTimes="0;0.5;1"
dur="20s"
repeatCount="indefinite"
/>
) : ( ) : (
<animate <animate attributeName="stroke-dashoffset" from="-10000" to="0" dur="10s" repeatCount="indefinite" />
attributeName="stroke-dashoffset"
from="-10000"
to="0"
dur="10s"
repeatCount="indefinite"
/>
)} )}
</path> </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 && ( {data?.label && (
<EdgeLabelRenderer> <EdgeLabelRenderer>
<div <div
+1 -1
View File
@@ -41,7 +41,7 @@ export interface ApiEdge {
speed?: string | null speed?: string | null
custom_color?: string | null custom_color?: string | null
path_style?: string | null path_style?: string | null
animated?: boolean animated?: boolean | 'snake' | 'flow' | 'none'
source_handle?: string | null source_handle?: string | null
target_handle?: string | null target_handle?: string | null
} }