feat(rack): add shift-click context modal for connections with color and edge type configurability
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user