Files
fusion/plugins/fusion-plugin-dependency-graph/src/edges.tsx
gsxdsm 47504ea0c8 fix(FN-3888): resolve dependency-graph plugin from src in dashboard build
The dashboard dynamically imports `@fusion-plugin-examples/dependency-graph/dashboard-view`, which resolved through the plugin's package.json exports to `dist/`. When plugin source was edited without rebuilding, stale `dist/` (extensionless ESM imports) made the import throw and the UI surfaced "Bundled plugin view unavailable". Add vite/vitest aliases mapping the plugin (and its `/dashboard-view` subpath) to `src/` so the dashboard never depends on `dist/`. Mirrors the existing pattern for hermes/openclaw/paperclip runtimes. Also extends the runtime-plugin alias regression test, and emits `.js` extensions from the plugin source for the CLI-bundled path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:44:44 -07:00

71 lines
2.4 KiB
TypeScript

import type { GraphEdge, GraphPosition } from "./types.js";
import "./GraphHighlight.css";
interface GraphEdgesProps {
edges: GraphEdge[];
positions: Map<string, GraphPosition>;
nodeWidth?: number;
nodeHeight?: number;
highlightedEdgeIds?: Set<string>;
}
const DEFAULT_NODE_WIDTH = 280;
const DEFAULT_NODE_HEIGHT = 100;
export function GraphEdges({
edges,
positions,
nodeWidth = DEFAULT_NODE_WIDTH,
nodeHeight = DEFAULT_NODE_HEIGHT,
highlightedEdgeIds,
}: GraphEdgesProps) {
const hasHighlights = Boolean(highlightedEdgeIds && highlightedEdgeIds.size > 0);
return (
<svg className="dependency-graph-edges" aria-hidden="true">
<defs>
<marker
id="dependency-graph-arrowhead"
markerWidth="10"
markerHeight="7"
refX="10"
refY="3.5"
orient="auto"
markerUnits="strokeWidth"
>
<path d="M 0 0 L 10 3.5 L 0 7 z" fill="var(--border)" />
</marker>
</defs>
{edges.map((edge) => {
const source = positions.get(edge.source);
const target = positions.get(edge.target);
if (!source || !target) return null;
const edgeId = `${edge.source}->${edge.target}`;
const isActiveHighlight = hasHighlights && (highlightedEdgeIds?.has(edgeId) ?? false);
const x1 = source.x + nodeWidth / 2;
const y1 = source.y + nodeHeight;
const x2 = target.x + nodeWidth / 2;
const y2 = target.y;
const controlY = y1 + (y2 - y1) / 2;
return (
<path
key={edgeId}
data-testid="dependency-edge"
data-edge-id={edgeId}
className={`dependency-graph-edge${isActiveHighlight ? " graph-edge--highlighted" : ""}${hasHighlights && !isActiveHighlight ? " graph-edge--dimmed" : ""}`}
d={`M ${x1} ${y1} C ${x1} ${controlY}, ${x2} ${controlY}, ${x2} ${y2}`}
fill="none"
stroke={isActiveHighlight ? "var(--todo)" : "var(--border)"}
strokeWidth={isActiveHighlight ? "var(--space-xs)" : "var(--btn-border-width)"}
opacity={hasHighlights && !isActiveHighlight ? 0.15 : 1}
markerEnd="url(#dependency-graph-arrowhead)"
style={{ transition: "opacity var(--transition-fast), stroke var(--transition-fast), stroke-width var(--transition-fast)" }}
/>
);
})}
</svg>
);
}