feat(rack): add shift-click context modal for connections with color and edge type configurability

This commit is contained in:
2026-03-22 21:35:10 -05:00
parent 72918bd87a
commit f1c1efd8d3
10 changed files with 277 additions and 17 deletions

View File

@@ -1,8 +1,9 @@
import { useEffect, useState, useMemo, useCallback } from 'react';
import { useRackStore } from '../../store/useRackStore';
import { cn } from '../../lib/utils';
export function ConnectionLayer() {
const { racks, cablingFromPortId } = useRackStore();
const { racks, cablingFromPortId, setActiveConfigConnectionId } = useRackStore();
const [coords, setCoords] = useState<Record<string, { x: number; y: number }>>({});
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
@@ -78,7 +79,7 @@ export function ConnectionLayer() {
}, [cablingFromPortId]);
const connections = useMemo(() => {
const conns: { id: string; from: string; to: string; color?: string; fromRackId: string; toRackId: string }[] = [];
const conns: { id: string; from: string; to: string; color?: string; edgeType?: string }[] = [];
racks.forEach((rack) => {
rack.modules.forEach((mod) => {
mod.ports.forEach((port) => {
@@ -88,8 +89,7 @@ export function ConnectionLayer() {
from: c.fromPortId,
to: c.toPortId,
color: c.color,
fromRackId: rack.id,
toRackId: '' // We don't easily know the destination rack without searching
edgeType: c.edgeType,
});
});
});
@@ -118,16 +118,25 @@ export function ConnectionLayer() {
const end = coords[conn.to];
if (!start || !end) return null;
// Calculate a slight curve. If ports are close, use a tighter curve.
const dx = Math.abs(end.x - start.x);
const dy = Math.abs(end.y - start.y);
const distance = Math.sqrt(dx*dx + dy*dy);
const curvature = Math.min(100, distance / 3);
let d = '';
if (conn.edgeType === 'straight') {
d = `M ${start.x} ${start.y} L ${end.x} ${end.y}`;
} else if (conn.edgeType === 'step') {
const midX = start.x + (end.x - start.x) / 2;
d = `M ${start.x} ${start.y} L ${midX} ${start.y} L ${midX} ${end.y} L ${end.x} ${end.y}`;
} else {
// default bezier
const dx = Math.abs(end.x - start.x);
const dy = Math.abs(end.y - start.y);
const distance = Math.sqrt(dx*dx + dy*dy);
const curvature = Math.min(100, distance / 3);
d = `M ${start.x} ${start.y} C ${start.x + curvature} ${start.y}, ${end.x - curvature} ${end.y}, ${end.x} ${end.y}`;
}
return (
<g key={conn.id} className="connection-group">
<path
d={`M ${start.x} ${start.y} C ${start.x + curvature} ${start.y}, ${end.x - curvature} ${end.y}, ${end.x} ${end.y}`}
d={d}
stroke={conn.color || '#3b82f6'}
strokeWidth="2.5"
fill="none"
@@ -136,11 +145,17 @@ export function ConnectionLayer() {
/>
{/* Thicker transparent helper for easier identification if we ever add hover interactions */}
<path
d={`M ${start.x} ${start.y} C ${start.x + curvature} ${start.y}, ${end.x - curvature} ${end.y}, ${end.x} ${end.y}`}
d={d}
stroke="transparent"
strokeWidth="10"
fill="none"
className="pointer-events-auto cursor-help"
className="pointer-events-auto cursor-pointer"
onClick={(e) => {
if (e.shiftKey) {
e.stopPropagation();
setActiveConfigConnectionId(conn.id);
}
}}
/>
</g>
);