Force-directed graph visualization for agent teams. Package: @claude-teams/agent-graph (isolated workspace package) - Space theme: bloom, particles, hex grid, depth stars - Members as hexagonal nodes with breathing glow - Tasks as pill cards in kanban columns (todo/wip/done/review/approved) per owner - Message particles along edges (real-time only) - Deterministic layout, Figma-style pan, scroll/pinch zoom - Clean Architecture: ports/adapters/strategies, ES #private classes Integration: features/agent-graph/ (adapter + overlay + tab) - Full-screen overlay (Cmd+Shift+G) + Pin as Tab - Graph button in Team section header - Frustum culling, zero per-frame allocations, adaptive fps - Performance overlay via ?perf query param Also: CI runs on all PR branches, features/CLAUDE.md architecture guide
39 lines
1 KiB
TypeScript
39 lines
1 KiB
TypeScript
/**
|
|
* Render strategy for process nodes.
|
|
*/
|
|
|
|
import type { GraphNode } from '../ports/types';
|
|
import type { NodeRenderStrategy, NodeRenderState } from './types';
|
|
import { drawProcesses } from '../canvas/draw-processes';
|
|
import { NODE, HIT_DETECTION } from '../constants/canvas-constants';
|
|
|
|
export class ProcessStrategy implements NodeRenderStrategy {
|
|
readonly kind = 'process' as const;
|
|
|
|
draw(ctx: CanvasRenderingContext2D, node: GraphNode, state: NodeRenderState): void {
|
|
drawProcesses(
|
|
ctx,
|
|
[node],
|
|
state.time,
|
|
state.isSelected ? node.id : null,
|
|
state.isHovered ? node.id : null,
|
|
);
|
|
}
|
|
|
|
hitTest(node: GraphNode, wx: number, wy: number): boolean {
|
|
const x = node.x ?? 0;
|
|
const y = node.y ?? 0;
|
|
const r = NODE.radiusProcess + HIT_DETECTION.agentPadding;
|
|
const dx = wx - x;
|
|
const dy = wy - y;
|
|
return dx * dx + dy * dy <= r * r;
|
|
}
|
|
|
|
getCollisionRadius(): number {
|
|
return NODE.radiusProcess + 10;
|
|
}
|
|
|
|
getChargeStrength(): number {
|
|
return -200;
|
|
}
|
|
}
|