agent-ecosystem/packages/agent-graph/src/ui/GraphOverlay.tsx
iliya 304a2a7f79 feat(graph): enhance GraphControls with settings toggle and improved zoom functionality
- Added a settings toggle to the GraphControls for better user interaction.
- Implemented event listeners to close settings when clicking outside or pressing Escape.
- Improved zoom controls to mark user interaction, preventing auto-fit adjustments during user actions.
- Refactored GraphOverlay to streamline rendering and position updates for selected nodes.
- Updated GraphView to utilize new layout effects for better performance and responsiveness.
2026-03-29 00:05:29 +02:00

76 lines
2.2 KiB
TypeScript

/**
* GraphOverlay — minimal built-in popover fallback.
* Used ONLY when host app doesn't provide renderOverlay prop.
* For full-featured popovers, use renderOverlay with project UI components.
*/
import type { GraphNode } from '../ports/types';
import type { GraphEventPort } from '../ports/GraphEventPort';
export interface GraphOverlayProps {
selectedNode: GraphNode | null;
events?: GraphEventPort;
onDeselect: () => void;
}
export function GraphOverlay({
selectedNode,
events,
onDeselect,
}: GraphOverlayProps): React.JSX.Element | null {
if (!selectedNode) return null;
return (
<div
className="rounded-lg p-3 min-w-[160px] max-w-[220px] shadow-xl"
style={{
background: 'rgba(10, 15, 30, 0.9)',
border: '1px solid rgba(100, 200, 255, 0.15)',
backdropFilter: 'blur(8px)',
}}
>
<div className="text-xs font-mono font-bold" style={{ color: selectedNode.color ?? '#aaeeff' }}>
{selectedNode.label}
</div>
{selectedNode.sublabel && (
<div className="mt-0.5 text-[10px] truncate" style={{ color: '#66ccff90' }}>
{selectedNode.sublabel}
</div>
)}
{selectedNode.role && (
<div className="mt-0.5 text-[10px]" style={{ color: '#66ccff70' }}>
{selectedNode.role}
</div>
)}
<div className="mt-2 flex gap-1">
{(selectedNode.kind === 'member' || selectedNode.kind === 'lead') && (
<FallbackButton
label="Message"
onClick={() => {
const ref = selectedNode.domainRef;
if (ref.kind === 'member') events?.onSendMessage?.(ref.memberName, ref.teamName);
onDeselect();
}}
/>
)}
<FallbackButton label="Close" onClick={onDeselect} />
</div>
</div>
);
}
function FallbackButton({ label, onClick }: { label: string; onClick: () => void }): React.JSX.Element {
return (
<button
onClick={onClick}
className="text-[10px] px-2 py-1 rounded font-mono cursor-pointer"
style={{
background: 'rgba(100, 200, 255, 0.08)',
border: '1px solid rgba(100, 200, 255, 0.15)',
color: '#aaeeff',
}}
>
{label}
</button>
);
}