@mp70/react-networks 0.1.5-alpha → 0.1.6-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/u-positioning.ts","../src/utils/status-colors.ts","../src/components/RackNode.tsx","../src/components/FiberNode.tsx","../src/components/FiberEdge.tsx","../src/components/PowerEdge.tsx","../src/components/SmoothStepFiberEdge.tsx","../src/components/StepFiberEdge.tsx","../src/types/index.ts","../src/utils/power-connectors.ts","../src/components/DeviceNode.tsx","../src/components/VerticalPDU.tsx","../src/components/SpliceNode.tsx","../src/utils/splice-positioning.ts","../src/components/SpliceTrayNode.tsx","../src/utils/fiber-colors.ts","../src/components/TubeNode.tsx","../src/components/CableNode.tsx","../src/core/store.ts","../src/core/hooks.ts","../src/utils/rack-geometry.ts","../src/utils/edge-connection.ts","../src/components/NetworkDiagram.tsx","../src/utils/inventory.ts","../src/utils/rack-schema.ts","../src/utils/splice-schema.ts"],"names":["getDefaultUNumberingDirection","getRackUNumberingDirection","rack","convertUPositionForDirection","uPosition","rackUHeight","direction","convertUPositionFromDirection","snapToUPosition","device","newPosition","allNodes","uHeight","startY","relativeY","physicalUPosition","calculatedUPosition","maxUPosition","snappedUPosition","isUPositionAvailable","availablePosition","findNextAvailableUPosition","snappedY","topLogicalUPosition","topPhysicalUPosition","snappedPhysicalUPosition","deviceUHeight","rackDevices","node","otherDevice","otherUPosition","otherUHeight","newDeviceStart","newDeviceEnd","otherDeviceStart","otherDeviceEnd","startFrom","u","calculateDevicePositionFromU","deviceHeight","deviceY","updateDeviceUPosition","newUPosition","validateAndSnapDevice","currentUPosition","validUPosition","getStatusColor","status","RackNode","data","selected","id","onViewChange","onRackFaceChange","isDragOver","label","ports","face","customHeaderText","getNodes","setNodes","useReactFlow","nodes","showUMarkers","setShowUMarkers","useState","toggleUNumberingDirection","newDirection","n","toggleFace","next","child","renderUPositions","positions","i","yPos","displayNumber","jsx","jsxs","e","FiberNode","Handle","Position","FiberEdge","sourceX","sourceY","targetX","targetY","sourcePosition","targetPosition","style","className","edgePath","labelX","labelY","getBezierPath","bandwidth","length","color","striped","baseEdgeStyle","Fragment","BaseEdge","EdgeLabelRenderer","PowerEdge","markerEnd","connectorType","baseStyle","SmoothStepFiberEdge","props","edgeStyle","ReactFlowSmoothStepEdge","getStepPath","isHorizontalFirst","path","midX","midY","StepFiberEdge","Width","POWER_CONNECTORS","getPowerPortStyle","connector","isHighPower","width","height","cornerStyle","getConnectorConfig","isHighPowerConnector","getPDUPortType","portIndex","getDeviceConnectorType","deviceName","name","DeviceNode","deviceType","manufacturer","role","rearPorts","view","currentFace","handleSideMap","portBlock","port","handleId","rackDeviceWidth","rackDeviceLeft","renderPortsFromArray","portBlocks","position","handles","portWidth","portHeight","_blockIndex","isPower","isConnected","portColor","handlePosition","handleStyle","baseTop","spacing","portStyle","isPatchPanel","handleType","oppositeType","renderHandles","renderAGGSwitchHandles","isSwitch","port1Top","port2Top","handle","bottomIndex","uplinkWidth","uplinkHeight","VerticalPDU","heightCm","powerPorts","widthPx","mgmt_unit","heightPx","renderPowerHandles","nCycles","portsPerCycle","_","c","idx","headerHeight","portSpacing","renderMgmtUnit","portType","leftPx","SpliceNode","lossDb","edges","useEdges","leftEdge","rightEdgeAsSource","rightEdgeAsTarget","rightEdge","leftColor","rightColor","bothConnected","HOLDER_HEIGHT_PX","TRAY_HEADER_HEIGHT","TRAY_BOTTOM_PADDING","HOLDERS_PER_TRAY","SPLICE_WIDTH_PX","TRAY_WIDTH_PX","SPLICE_CENTER_X","snapToSplicePosition","splice","tray","calculatedPosition","snappedPosition","isHolderPositionAvailable","findNextAvailableHolderPosition","pos","calculateSplicePositionFromNumber","holderPosition","spliceY","SpliceTrayNode","showHolderMarkers","setShowHolderMarkers","renderHolderPositions","FIBER_COLORS_12","baseColorFor","normalizedId","isStriped","fiberSolidOrStriped","base","getFiberColor","TubeNode","fibersPerTube","tubeIndex","startOn","fibers","handleSize","handleSpacing","padding","borderWidth","totalHandlesWidth","tubeBorderColor","tubeConnectionHandleId","tubeConnectionHandleSize","connectionHandleStyle","getTubeConnectionPosition","innerWidth","startLeft","reverseColors","fiberIdx","fiberStyle","baseColor","left","top","handleBackground","fiberHandleId","React","CableNode","tubeCount","providedFiberCount","cableId","rawTubeStartIndex","borderStyle","tubes","tubeStartIndex","innerPaddingTop","totalFibers","primaryText","secondaryText","firstTubeColor","borderColor","useStripedBorder","tubeIdx","tubeStyle","tubeHandleId","innerContent","defaultValidateConnection","params","ctx","sourceAlready","targetAlready","sourceHandleId","targetHandleId","sourceNode","targetNode","isPowerHandle","h","looksLikeDevicePower","isPduPower","isNetworkHandle","looksLikeNetwork","isCustomPortName","sourceIsPower","targetIsPower","sourceIsNetwork","targetIsNetwork","isPduSource","isPduTarget","deviceNode","pduNode","eSourceIsPower","eTargetIsPower","involvesDevice","getHandleSide","normalizedHandleId","frontBlocks","rearBlocks","block","createNetworkDiagramStore","initial","options","state","listeners","partial","l","listener","edge","deviceView","side","targetHandle","targetHandleLc","isStandardNetworkHandle","nodeId","useNetworkDiagram","store","subscribe","cb","getSnapshot","useSyncExternalStore","useNodes","useSelectEdgeZIndex","getRackBounds","rackWidth","rackHeight","rackLeft","rackRight","rackTop","rackBottom","isPointInRack","point","bounds","findNearestRack","racks","nearestRack","minDistance","distance","replaceEdge","connection","edgeType","selectEdgeZIndex","findBy","existingEdge","filtered","edgeFromAddEdge","addEdge","newEdge","zIndex","edgeWithMetadata","createNodeTypes","getDragOverRackId","edgeTypes","NetworkDiagramInner","initialNodes","initialEdges","externalOnNodesChange","externalOnEdgesChange","debug","onNodeClick","onEdgeClick","alignRacksToBottom","colorMode","onInit","onFlowMethods","showDownloadButton","downloadButtonPosition","downloadButtonText","downloadButtonStyle","allowReconnectExisting","useSmoothstepEdgesForTubes","isControlled","localStore","storeNodes","storeEdges","reactFlowNodes","onNodesChange","useNodesState","reactFlowEdges","setEdges","onEdgesChange","useEdgesState","reactFlowWrapper","useRef","toObject","setViewport","setReactFlowNodes","setReactFlowEdges","useEffect","toPng","onDownload","useCallback","dataUrl","link","error","dragOverRackId","setDragOverRackId","dragOverRackIdRef","onViewChangeRef","onRackFaceChangeRef","memoizedNodeTypes","useMemo","rackId","memoizedEdgeTypes","latestNodesRef","latestEdgesRef","rackBottoms","r","minBottom","maxBottom","baselineBottom","nextNodes","currentBottom","delta","getNodeById","deriveFiberColorFromSource","sourceNodeId","sourceHandle","fiberNumStr","fiberNum","tubeNumStr","tubeNum","nodeData","eds","newZIndex","updatedNodes","parentTray","parentRack","index","handleNodesChange","changes","updatedChanges","change","snappedResult","updatedNode","rackNode","absoluteX","absoluteY","handleNodeDragStart","_event","_node","handleNodeDrag","_nodes","handleNodeDragStop","relativeX","isValidConnection","validation","onConnect","sourceNodeData","isSwitchSource","looksLikePowerTarget","looksLikeNetworkTarget","isTubeToCable","isCableToTube","isTubeConnection","edgeData","colorInfo","newEdges","edgeToAdd","setAnimatingEdges","prev","onEdgeUpdate","oldEdge","newConnection","oldSourceHandle","oldTargetHandle","newSourceHandle","newTargetHandle","handleNodeClick","event","isCommandClick","parentNode","nds","currentView","nextView","handleNodeDoubleClick","handleEdgeClick","selectedNode","setSelectedNode","animatingEdges","useOnSelectionChange","handleConnectStart","handleConnectEnd","toggleSelectedFace","hasRear","hasFront","edgesWithAnimation","sourceSide","targetSide","sourceView","targetView","sourceIsRear","targetIsRear","nextStyle","ReactFlow","filteredChanges","edgeToRemove","Background","Controls","MiniMap","Panel","NetworkDiagram","ReactFlowProvider","inventoryRackToNetworkNode","inventoryDeviceToNetworkNode","inventoryCableToNetworkEdge","cable","getDeviceId","term","dev","termADeviceId","termBDeviceId","inventoryToNetworkDiagram","generateLayout","rackNodes","deviceNodes","otherNodes","DevicePlacementError","deviceId","conflictWith","validateRackDevicePlacements","_options","conflicts","outOfBounds","deviceA","deviceAStart","deviceAEnd","j","deviceB","deviceBStart","deviceBEnd","createDeviceNode","deviceTypeMapping","nodeType","createRackNode","buildNodesFromRackConfig","conflictPolicy","validatePlacements","errors","conflict","bound","adjustedDevice","createRackConfigFromNodes","devices","addDeviceToRack","removeDeviceFromRack","SplicePlacementError","trayId","spliceId","holder","validateSplicePlacements","spliceA","spliceB","createSpliceNode","createTrayNode","buildNodesFromSpliceConfig","trays","spliceNodes","trayNode","spliceNode","allNodesForConflictCheck","adjustedSplice","createSpliceConfigFromNodes","trayNodes","splices","updateSpliceHolderPosition","newHolder","addSpliceToTray","removeSpliceFromTray"],"mappings":"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","file":"index.mjs","sourcesContent":["import { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\n\n/**\n * Get the default U numbering direction\n */\nexport const getDefaultUNumberingDirection = (): UNumberingDirection => 'bottom-up';\n\n/**\n * Get the U numbering direction for a rack\n */\nexport const getRackUNumberingDirection = (rack: NetworkNode): UNumberingDirection => {\n return rack.data.uNumberingDirection || getDefaultUNumberingDirection();\n};\n\n/**\n * Convert U position number based on numbering direction\n * For bottom-up: U position 1 is at the bottom\n * For top-down: U position 1 is at the top\n */\nexport const convertUPositionForDirection = (\n uPosition: number,\n rackUHeight: number,\n direction: UNumberingDirection\n): number => {\n if (direction === 'bottom-up') {\n // For bottom-up, U position 1 is at the bottom, so we need to flip the numbering\n return rackUHeight - uPosition + 1;\n }\n // For top-down, U position 1 is at the top, so no conversion needed\n return uPosition;\n};\n\n/**\n * Convert U position number back to physical position\n */\nexport const convertUPositionFromDirection = (\n uPosition: number,\n rackUHeight: number,\n direction: UNumberingDirection\n): number => {\n if (direction === 'bottom-up') {\n // For bottom-up, convert back from the flipped numbering\n return rackUHeight - uPosition + 1;\n }\n // For top-down, no conversion needed\n return uPosition;\n};\n\n/**\n * Calculate U position from device Y coordinate within a rack\n */\nexport const calculateUPositionFromY = (\n deviceY: number,\n rackY: number,\n rackUHeight: number = 42,\n direction: UNumberingDirection = 'bottom-up'\n): number => {\n const startY = RACK_HEADER_HEIGHT; // Start at top of rack body\n const relativeY = deviceY - rackY - startY;\n const physicalUPosition = Math.max(1, Math.min(rackUHeight, Math.round(relativeY / U_HEIGHT_PX) + 1));\n \n // Convert to the appropriate numbering direction\n return convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n};\n\n/**\n * Snap a device position to the nearest U position within a rack\n */\nexport const snapToUPosition = (\n device: NetworkNode,\n rack: NetworkNode,\n newPosition: { x: number; y: number },\n allNodes: NetworkNode[]\n): { x: number; y: number; uPosition?: number } => {\n if (!device.parentId || device.parentId !== rack.id) {\n return newPosition;\n }\n\n const uHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n const direction = getRackUNumberingDirection(rack);\n \n // Calculate U position based on Y coordinate\n const startY = RACK_HEADER_HEIGHT; // After header\n \n // Calculate which U position this corresponds to\n // Y coordinate represents the MIDDLE of the device for better drag behavior\n const relativeY = newPosition.y - startY; // child position is already parent-relative\n const physicalUPosition = Math.round(relativeY / U_HEIGHT_PX) + 1;\n \n // Convert to logical U position based on direction\n // For snapping, we want to find the U position that corresponds to the Y position\n // The Y position represents where the user wants to place the device\n let calculatedUPosition;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // But the Y position represents the TOP of the device\n // So we need to adjust for the device height\n const logicalPosition = convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n calculatedUPosition = logicalPosition - uHeight + 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n const logicalPosition = convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n calculatedUPosition = logicalPosition;\n }\n \n // Ensure the device doesn't extend beyond the rack boundaries\n // For multi-U devices, we need to ensure the entire device fits\n const maxUPosition = rackUHeight - uHeight + 1;\n let snappedUPosition = Math.max(1, Math.min(maxUPosition, calculatedUPosition));\n \n // For top-down numbering, ensure we can place devices at the top (U1)\n if (direction === 'top-down' && calculatedUPosition <= 1) {\n snappedUPosition = 1;\n }\n \n // Debug logging (commented out for production)\n // console.log('SnapToUPosition Debug:', {\n // deviceId: device.id,\n // newPosition,\n // rackPosition: rack.position,\n // startY,\n // relativeY,\n // physicalUPosition,\n // calculatedUPosition,\n // snappedUPosition,\n // uHeight,\n // rackUHeight,\n // direction\n // });\n \n // Check if the calculated position is available, if not find the nearest available position\n if (!isUPositionAvailable(rack, device, snappedUPosition, allNodes)) {\n // Try to find the nearest available position\n const availablePosition = findNextAvailableUPosition(rack, device, allNodes, snappedUPosition);\n if (availablePosition !== snappedUPosition) {\n snappedUPosition = availablePosition;\n }\n }\n \n // Snap to exact U position - ensure devices are exactly on U boundaries\n // Account for device border (1px) to align properly with U grid\n // The Y coordinate should ALWAYS represent the TOP of the device\n // For bottom-up direction, we need to calculate the Y position of the TOP of the device\n let snappedY;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // So we need to calculate the Y position of the TOP of the device\n const topLogicalUPosition = snappedUPosition + uHeight - 1;\n const topPhysicalUPosition = convertUPositionFromDirection(topLogicalUPosition, rackUHeight, direction);\n snappedY = startY + (topPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n const snappedPhysicalUPosition = convertUPositionFromDirection(snappedUPosition, rackUHeight, direction);\n snappedY = startY + (snappedPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n }\n \n return {\n x: newPosition.x,\n y: snappedY,\n uPosition: snappedUPosition,\n };\n};\n\n/**\n * Check if a U position is available in a rack\n */\nexport const isUPositionAvailable = (\n rack: NetworkNode,\n device: NetworkNode,\n uPosition: number,\n allNodes: NetworkNode[]\n): boolean => {\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n // Check bounds\n if (uPosition < 1 || uPosition + deviceUHeight - 1 > rackUHeight) {\n return false;\n }\n \n // Check for conflicts with other devices in the same rack\n const rackDevices = allNodes.filter(node => \n node.type === 'device' && \n node.parentId === rack.id && \n node.id !== device.id\n );\n \n for (const otherDevice of rackDevices) {\n const otherUPosition = otherDevice.data.uPosition || 1;\n const otherUHeight = otherDevice.data.uHeight || 1;\n \n // Check if the new device would overlap with existing device\n const newDeviceStart = uPosition;\n const newDeviceEnd = uPosition + deviceUHeight - 1;\n const otherDeviceStart = otherUPosition;\n const otherDeviceEnd = otherUPosition + otherUHeight - 1;\n \n if (newDeviceStart <= otherDeviceEnd && newDeviceEnd >= otherDeviceStart) {\n return false; // Overlap detected\n }\n }\n \n return true;\n};\n\n/**\n * Find the next available U position in a rack\n */\nexport const findNextAvailableUPosition = (\n rack: NetworkNode,\n device: NetworkNode,\n allNodes: NetworkNode[],\n startFrom: number = 1\n): number => {\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n for (let u = startFrom; u <= rackUHeight - deviceUHeight + 1; u++) {\n if (isUPositionAvailable(rack, device, u, allNodes)) {\n return u;\n }\n }\n \n return 1; // Fallback to position 1\n};\n\n/**\n * Calculate device position based on U position within a rack\n */\nexport const calculateDevicePositionFromU = (\n rack: NetworkNode,\n uPosition: number,\n deviceHeight: number = 1\n): { x: number; y: number } => {\n const startY = RACK_HEADER_HEIGHT; // After header\n const direction = getRackUNumberingDirection(rack);\n const rackUHeight = rack.data.uHeight || 42;\n \n // Convert U position to physical position\n const physicalUPosition = convertUPositionFromDirection(uPosition, rackUHeight, direction);\n \n // Position device so its TOP edge aligns with the U position\n // For initial positioning, we place the device at the exact U position specified\n let deviceY;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // So we need to calculate the Y position of the TOP of the device\n const topLogicalUPosition = uPosition + deviceHeight - 1;\n const topPhysicalUPosition = convertUPositionFromDirection(topLogicalUPosition, rackUHeight, direction);\n deviceY = startY + (topPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n deviceY = startY + (physicalUPosition - 1) * U_HEIGHT_PX - 1;\n }\n \n return {\n x: 0, // Align with rack left edge (relative to parent)\n y: deviceY,\n };\n};\n\n/**\n * Update device U position and recalculate position\n */\nexport const updateDeviceUPosition = (\n device: NetworkNode,\n rack: NetworkNode,\n newUPosition: number\n): NetworkNode => {\n const deviceHeight = device.data.uHeight || 1;\n const newPosition = calculateDevicePositionFromU(rack, newUPosition, deviceHeight);\n \n return {\n ...device,\n position: newPosition,\n data: {\n ...device.data,\n uPosition: newUPosition,\n },\n };\n};\n\n/**\n * Validate and snap device to valid U position\n */\nexport const validateAndSnapDevice = (\n device: NetworkNode,\n rack: NetworkNode\n): NetworkNode => {\n const currentUPosition = device.data.uPosition || 1;\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n // Ensure U position is within bounds\n const validUPosition = Math.max(1, Math.min(rackUHeight - deviceUHeight + 1, currentUPosition));\n \n if (validUPosition !== currentUPosition) {\n return updateDeviceUPosition(device, rack, validUPosition);\n }\n \n return device;\n};\n","import { DeviceStatus } from '../types';\n\n/**\n * Get the color code for a device status\n * @param status - The device status\n * @returns Hex color code for the status\n * @public\n */\nexport function getStatusColor(status: DeviceStatus | string): string {\n switch (status) {\n case 'active':\n return '#10b981';\n case 'inactive':\n return '#6b7280';\n case 'maintenance':\n return '#f59e0b';\n default:\n return '#6b7280';\n }\n}\n\n","import React, { useState } from 'react';\nimport { NodeProps, useReactFlow } from 'reactflow';\nimport { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT, RACK_WIDTH_PX } from '../utils/constants';\nimport { getRackUNumberingDirection, convertUPositionForDirection } from '../utils/u-positioning';\nimport { getStatusColor } from '../utils/status-colors';\n\ninterface RackNodeProps extends NodeProps<NetworkNode['data']> {\n onViewChange?: (nodeId: string, view: 'front' | 'rear') => void;\n onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void;\n isDragOver?: boolean;\n}\n\nexport const RackNode: React.FC<RackNodeProps> = ({ data, selected, id, onViewChange, onRackFaceChange, isDragOver = false }) => {\n const { \n label, \n ports = 0, \n status = 'active',\n uHeight = 42, // Standard rack height\n face = 'front',\n customHeaderText\n } = data;\n \n const { getNodes, setNodes } = useReactFlow();\n const nodes = getNodes();\n const [showUMarkers, setShowUMarkers] = useState(true);\n \n const toggleUNumberingDirection = () => {\n const currentDirection = getRackUNumberingDirection({ data } as NetworkNode);\n const newDirection: UNumberingDirection = currentDirection === 'bottom-up' ? 'top-down' : 'bottom-up';\n \n setNodes(nodes => nodes.map(n => \n n.id === id \n ? { ...n, data: { ...n.data, uNumberingDirection: newDirection } }\n : n\n ));\n };\n\n \n const toggleFace = () => {\n const next = face === 'front' ? 'rear' : 'front';\n \n if (onRackFaceChange) {\n onRackFaceChange(id, next);\n // Also update child devices via onViewChange if provided\n if (onViewChange) {\n const childNodes = nodes.filter(n => n.parentId === id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n }\n } else if (onViewChange) {\n // Use external onViewChange for devices\n const childNodes = nodes.filter(n => n.parentId === id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n } else {\n // Fallback to internal state management\n setNodes(nodes => nodes.map(n => \n n.id === id \n ? { ...n, data: { ...n.data, face: next } }\n : n.parentId === id \n ? { ...n, data: { ...n.data, view: next } } // Use 'view' for devices\n : n\n ));\n }\n };\n\n // Generate U position markers aligned to rack origin\n const renderUPositions = () => {\n const positions = [];\n const startY = RACK_HEADER_HEIGHT; // Start after header from rack origin\n const direction = getRackUNumberingDirection({ data } as NetworkNode);\n \n for (let i = 1; i <= uHeight; i++) {\n const yPos = startY + (i - 1) * U_HEIGHT_PX - 4; // Align with device positioning, shifted up 3px\n // Convert the physical position to the display number based on direction\n const displayNumber = convertUPositionForDirection(i, uHeight, direction);\n \n positions.push(\n <div\n key={i}\n style={{\n position: 'absolute',\n left: '-35px',\n top: `${yPos}px`,\n background: '#374151',\n color: '#9ca3af',\n padding: '2px 4px',\n borderRadius: '2px',\n fontSize: '8px',\n fontWeight: 'bold',\n width: '28px',\n textAlign: 'center',\n border: '1px solid #4b5563',\n zIndex: 10,\n height: `${U_HEIGHT_PX}px`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n >\n {displayNumber}\n </div>\n );\n }\n return positions;\n };\n\n\n return (\n <div\n className={`rack-node ${selected ? 'selected' : ''} ${isDragOver ? 'drag-over' : ''}`}\n style={{\n background: 'transparent',\n border: `2px solid ${getStatusColor(status)}`,\n borderRadius: '8px',\n padding: 0,\n width: `${RACK_WIDTH_PX}px`, // Fixed width for parent node\n height: `${RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX}px`, // Header + exact U area\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: isDragOver \n ? '0 0 20px #3b82f6, 0 0 40px #3b82f6, 0 0 60px #3b82f6' \n : selected \n ? '0 0 0 2px #3b82f6' \n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n transition: 'box-shadow 0.2s ease-in-out',\n }}\n >\n {/* Rack Header */}\n <div style={{ \n textAlign: 'center', \n marginBottom: 0, \n zIndex: 2, \n background: '#1f2937', \n padding: '8px',\n position: 'relative',\n height: `${RACK_HEADER_HEIGHT}px`, // Fixed header height\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n }}>\n <div style={{ fontWeight: 'bold', marginBottom: '4px' }}>{label}</div>\n <div style={{ fontSize: '10px', color: '#9ca3af' }}>\n {customHeaderText ? (\n <span style={{ color: '#fbbf24', fontWeight: 'bold' }}>{customHeaderText}</span>\n ) : (\n <span>{typeof ports === 'number' ? ports : 0} ports</span>\n )} • {uHeight}U • {face}\n </div>\n <div style={{ display: 'flex', gap: '4px', position: 'absolute', top: '4px', right: '4px' }}>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); setShowUMarkers(!showUMarkers); }}\n style={{\n background: showUMarkers ? '#10b981' : '#374151',\n color: showUMarkers ? '#ffffff' : '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`${showUMarkers ? 'Hide' : 'Show'} U markers`}\n >\n U\n </button>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); toggleUNumberingDirection(); }}\n style={{\n background: '#374151',\n color: '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`Switch U numbering to ${getRackUNumberingDirection({ data } as NetworkNode) === 'bottom-up' ? 'top-down' : 'bottom-up'}`}\n >\n {getRackUNumberingDirection({ data } as NetworkNode) === 'bottom-up' ? '↑↓' : '↓↑'}\n </button>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); toggleFace(); }}\n style={{\n background: '#374151',\n color: '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`Switch to ${face === 'front' ? 'rear' : 'front'} view`}\n >\n {face === 'front' ? '⇄ Rear' : '⇄ Front'}\n </button>\n </div>\n </div>\n \n {/* Rack Body - transparent background; devices are positioned relative to rack origin */}\n <div\n style={{\n flex: 1,\n background: 'transparent',\n // no borders to avoid pixel offsets\n position: 'relative',\n minHeight: `${uHeight * U_HEIGHT_PX}px`,\n overflow: 'hidden',\n }}\n />\n\n {/* Overlay for U markers aligned to rack origin */}\n {showUMarkers && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n }}\n >\n {renderUPositions()}\n </div>\n )}\n \n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\n\nexport const FiberNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { label, status = 'active' } = data;\n\n return (\n <div\n className={`fiber-node ${selected ? 'selected' : ''}`}\n style={{\n background: '#1f2937',\n border: `2px solid ${getStatusColor(status)}`,\n borderRadius: '50%',\n width: '60px',\n height: '60px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '10px',\n fontWeight: 'bold',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n }}\n >\n <Handle type=\"target\" position={Position.Top} />\n <Handle type=\"source\" position={Position.Bottom} />\n <Handle type=\"target\" position={Position.Left} />\n <Handle type=\"source\" position={Position.Right} />\n \n <div style={{ textAlign: 'center' }}>\n <div style={{ fontSize: '8px', lineHeight: '1.2' }}>{label}</div>\n </div>\n \n <div\n style={{\n position: 'absolute',\n bottom: '4px',\n left: '50%',\n transform: 'translateX(-50%)',\n width: '8px',\n height: '8px',\n background: getStatusColor(status),\n borderRadius: '50%',\n }}\n />\n </div>\n );\n};\n","import React from 'react';\nimport { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\nexport const FiberEdge: React.FC<EdgeProps<NetworkEdge['data']> & { className?: string }> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n style = {},\n className,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n const { bandwidth, length, color = '#00FFFF', striped = false } = data || {};\n const isAnimating = className?.includes('edge-connecting');\n\n // Use BaseEdge so React Flow layering/zIndex works consistently like power edges\n // Spread style first, then override with our specific properties to ensure data color takes precedence\n const baseEdgeStyle = {\n ...style, // includes zIndex from React Flow\n stroke: color, // Override any stroke from style prop with our data color\n strokeWidth: selected ? 3 : 2,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n\n return (\n <>\n {/* Base colored stroke */}\n <BaseEdge \n id={id} \n path={edgePath} \n style={baseEdgeStyle}\n />\n {/* Overlay black dashed stroke to simulate tracer for 13–24 */}\n {striped && (\n <BaseEdge\n id={`${id}-stripe`}\n path={edgePath}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1.5,\n strokeDasharray: '6 6',\n opacity: 0.9,\n }}\n />\n )}\n <EdgeLabelRenderer>\n {selected && data && (bandwidth || length) && (\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n background: '#1f2937',\n padding: '4px 8px',\n borderRadius: '4px',\n fontSize: '10px',\n color: 'white',\n fontFamily: 'monospace',\n border: `1px solid ${color}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {bandwidth && <div>{bandwidth}</div>}\n {length && <div>{length}m</div>}\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\n};\n","import React from 'react';\nimport { EdgeProps, getBezierPath, BaseEdge } from 'reactflow';\n\nexport const PowerEdge: React.FC<EdgeProps> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n}) => {\n const [edgePath] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Determine connector type based on data\n const connectorType = data?.connectorType || 'C13';\n\n // Different styling for different connector types\n const getEdgeStyle = () => {\n const baseStyle = {\n stroke: data?.color || '#f59e0b',\n strokeWidth: connectorType === 'C19' ? 5 : 3, // Thicker for C19 (higher power)\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n ...style, // This includes zIndex from React Flow\n };\n\n\n // C19 (16A) gets solid line, C13 (10A) gets dashed\n if (connectorType === 'C19') {\n return {\n ...baseStyle,\n strokeDasharray: 'none', // Solid line for high power\n };\n } else {\n return {\n ...baseStyle,\n strokeDasharray: '6,3', // Dashed line for standard power\n };\n }\n };\n\n return (\n <BaseEdge\n id={id}\n path={edgePath}\n markerEnd={markerEnd}\n style={getEdgeStyle()}\n />\n );\n};\n","import React from 'react';\nimport { EdgeProps, SmoothStepEdge as ReactFlowSmoothStepEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * SmoothStepFiberEdge\n * - Wrapper around React Flow's SmoothStepEdge that applies color from edge data\n * - Used for cable-to-tube connections\n */\nexport const SmoothStepFiberEdge: React.FC<EdgeProps<NetworkEdge['data']>> = ({\n data,\n selected,\n style = {},\n ...props\n}) => {\n const { color = '#00FFFF' } = data || {};\n\n // Apply color from data to the edge style\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: selected ? 4 : 3,\n } as React.CSSProperties;\n\n return (\n <ReactFlowSmoothStepEdge\n {...props}\n data={data}\n selected={selected}\n style={edgeStyle}\n />\n );\n};\n\n","import React from 'react';\nimport { EdgeProps, BaseEdge, Position } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * Calculate a step path (right-angle path) between two points\n * The path goes horizontally first, then vertically (or vice versa)\n */\nfunction getStepPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n}: {\n sourceX: number;\n sourceY: number;\n targetX: number;\n targetY: number;\n sourcePosition: Position;\n targetPosition: Position;\n}): string {\n // Calculate the midpoint for the step\n // For step edges, we go horizontally first, then vertically\n const isHorizontalFirst = sourcePosition === Position.Left || sourcePosition === Position.Right;\n \n let path: string;\n \n if (isHorizontalFirst) {\n // Go horizontal first, then vertical\n const midX = (sourceX + targetX) / 2;\n path = `M ${sourceX},${sourceY} L ${midX},${sourceY} L ${midX},${targetY} L ${targetX},${targetY}`;\n } else {\n // Go vertical first, then horizontal\n const midY = (sourceY + targetY) / 2;\n path = `M ${sourceX},${sourceY} L ${sourceX},${midY} L ${targetX},${midY} L ${targetX},${targetY}`;\n }\n \n return path;\n}\n\n/**\n * StepFiberEdge\n * - Custom step edge that applies color from edge data\n * - Used for tube-to-cable connections\n * - Supports striped edges for fibers 13-24\n */\nexport const StepFiberEdge: React.FC<EdgeProps<NetworkEdge['data']>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n style = {},\n ...props\n}) => {\n const { color = '#00FFFF', striped = false } = data || {};\n\n // Calculate step path\n const edgePath = getStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Apply color from data to the edge style\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: selected ? 3 : 2,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n return (\n <>\n {/* Base colored stroke */}\n <BaseEdge\n id={id}\n path={edgePath}\n style={edgeStyle}\n />\n {/* Overlay black dashed stroke to simulate tracer for 13–24 */}\n {striped && (\n <BaseEdge\n id={`${id}-stripe`}\n path={edgePath}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1.5,\n strokeDasharray: '6 6',\n opacity: 0.9,\n }}\n />\n )}\n </>\n );\n};\n\n","/**\n * Rack device width configuration\n * @public\n */\nexport enum Width {\n /** Full width device (19\" rack width) */\n FULL = 'full',\n /** Half width device (9.5\" rack width) */\n HALF = 'half'\n}\n\n/**\n * Port configuration for network devices\n * @public\n */\nexport interface Port {\n /** Display label for the port */\n label: string;\n /** Whether the port is currently connected */\n connected: boolean;\n /** Type of port for styling and validation */\n type?: 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';\n /** Cable type for connection validation */\n cableType?: 'smf' | 'cat6' | 'om3' | 'om4' | 'om5' | 'cat5e' | 'cat6a' | 'cat7' | 'fiber' | 'ethernet';\n}\n\n/**\n * Group of related ports on a device\n * @public\n */\nexport interface PortBlock {\n /** Name of the port group */\n name: string;\n /** Array of ports in this group */\n ports: Port[];\n}\n\n/**\n * Network node types supported by the diagram\n * @public\n */\nexport type NetworkNodeType = \n | 'rack' \n | 'switch' \n | 'router' \n | 'server' \n | 'fiber' \n | 'patch-panel' \n | 'device' \n | 'vertical-pdu'\n | 'splice'\n | 'splice-tray'\n | 'tube'\n | 'cable';\n\n/**\n * Device status states\n * @public\n */\nexport type DeviceStatus = 'active' | 'inactive' | 'maintenance';\n\n/**\n * Device view orientations\n * @public\n */\nexport type DeviceView = 'front' | 'rear';\n\n/**\n * Power port side configuration\n * @public\n */\nexport type PowerSide = 'left' | 'right';\n\n/**\n * U numbering direction for racks\n * @public\n */\nexport type UNumberingDirection = 'bottom-up' | 'top-down';\n\n/**\n * Network node data structure\n * @public\n */\nexport interface NetworkNode {\n /** Unique identifier for the node */\n id: string;\n /** Type of network node */\n type: NetworkNodeType;\n /** Position coordinates in the diagram */\n position: { x: number; y: number };\n /** Parent node ID for React Flow sub-flows */\n parentId?: string;\n /** Node extent for sub-flows */\n extent?: 'parent' | [[number, number], [number, number]];\n /** Node data and configuration */\n data: {\n /** Display label for the node */\n label: string;\n /** Port configurations for the device */\n ports?: PortBlock[];\n /** List of connected node IDs */\n connections?: string[];\n /** Current status of the device */\n status?: DeviceStatus;\n /** NetBox integration ID */\n netboxId?: number;\n /** NetBox object type */\n netboxType?: 'device' | 'rack' | 'interface' | 'cable';\n /** Rack height in U units */\n uHeight?: number;\n /** Device position within rack in U units */\n uPosition?: number;\n /** Current view orientation */\n view?: DeviceView;\n /** Device type specification */\n deviceType?: string;\n /** Device manufacturer */\n manufacturer?: string;\n /** Device role in network */\n role?: string;\n /** Device width configuration */\n width?: Width;\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** Power port side for rear view */\n powerSide?: PowerSide;\n /** Vertical PDU height in centimeters */\n heightCm?: number;\n /** Number of AC power ports */\n powerPorts?: number;\n /** U numbering direction for rack nodes */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack nodes */\n customHeaderText?: string;\n /** Holder position within tray (1-12) for splice nodes */\n holderPosition?: number;\n /** Loss value in dB for splice nodes */\n lossDb?: number;\n /** Additional custom properties */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n };\n}\n\n/**\n * Network edge types\n * @public\n */\nexport type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step';\n\n/**\n * Network edge data structure\n * @public\n */\nexport interface NetworkEdge {\n /** Unique identifier for the edge */\n id: string;\n /** Source node ID */\n source: string;\n /** Target node ID */\n target: string;\n /** Source handle/port ID */\n sourceHandle?: string;\n /** Target handle/port ID */\n targetHandle?: string;\n /** Type of network connection */\n type?: NetworkEdgeType;\n /** Edge data and configuration */\n data?: {\n /** Connection bandwidth */\n bandwidth?: string;\n /** Cable length */\n length?: number;\n /** Edge color for styling */\n color?: string;\n /** Edge kind for styling/validation */\n kind?: 'fiber' | 'power' | 'network';\n /** Additional custom properties */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n };\n}\n\n/**\n * Rack device types\n * @public\n */\nexport type RackDeviceType = 'server' | 'switch' | 'router' | 'patch-panel' | 'ups';\n\n/**\n * Rack configuration structure\n * @public\n */\nexport interface RackConfig {\n /** Unique rack identifier */\n id: string;\n /** Rack display name */\n name: string;\n /** Rack position coordinates */\n position: { x: number; y: number };\n /** Rack height in U units */\n units: number;\n /** U numbering direction (default: 'bottom-up') */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack */\n customHeaderText?: string;\n /** Devices mounted in the rack */\n devices: RackDevice[];\n}\n\n/**\n * Device mounted in a rack\n * @public\n */\nexport interface RackDevice {\n /** Unique device identifier */\n id: string;\n /** Device display name */\n name: string;\n /** Starting U position in rack */\n unit: number;\n /** Device height in U units */\n height: number;\n /** Device type */\n type: RackDeviceType;\n /** Device width configuration */\n width?: Width;\n /** Device role in network */\n role?: string;\n /** Front port configurations */\n ports?: PortBlock[];\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** Power port side for rear view */\n powerSide?: PowerSide;\n /** Connected device IDs */\n connections?: string[];\n}\n\n/**\n * Fiber cable types\n * @public\n */\nexport type FiberCableType = 'single-mode' | 'multi-mode';\n\n/**\n * Fiber cable configuration\n * @public\n */\nexport interface FiberCable {\n /** Unique cable identifier */\n id: string;\n /** Cable display name */\n name: string;\n /** Fiber cable type */\n type: FiberCableType;\n /** Cable length */\n length: number;\n /** Cable color for visualization */\n color: string;\n /** Connection endpoints */\n connections: {\n /** Source connection point */\n from: string;\n /** Target connection point */\n to: string;\n };\n}\n\n/**\n * Splice configuration structure\n * @public\n */\nexport interface SpliceConfig {\n /** Unique splice identifier */\n id: string;\n /** Splice display name */\n name: string;\n /** Holder position within tray (1-12) */\n holder: number;\n /** Loss value in dB */\n lossDb?: number;\n}\n\n/**\n * Splice tray configuration structure\n * @public\n */\nexport interface SpliceTrayConfig {\n /** Unique tray identifier */\n id: string;\n /** Tray display name */\n name: string;\n /** Tray position coordinates */\n position: { x: number; y: number };\n /** Splices in this tray */\n splices: SpliceConfig[];\n}\n\n// Inventory/CMDB integrations are generic and not tied to specific vendors\n\n/**\n * Network diagram component props\n * @public\n */\nexport interface NetworkDiagramProps {\n /** Controlled nodes array */\n nodes?: NetworkNode[];\n /** Controlled edges array */\n edges?: NetworkEdge[];\n /** Callback when nodes change (controlled mode) */\n onNodesChange?: (nodes: NetworkNode[]) => void;\n /** Callback when edges change (controlled mode) */\n onEdgesChange?: (edges: NetworkEdge[]) => void;\n /** Initial nodes for uncontrolled mode */\n initialNodes?: NetworkNode[];\n /** Initial edges for uncontrolled mode */\n initialEdges?: NetworkEdge[];\n /** Headless store injection */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n store?: any;\n /** Enable debug mode */\n debug?: boolean;\n /** Callback when a node is clicked or selection changes (null when deselected) */\n onNodeClick?: (node: NetworkNode | null) => void;\n /** Callback when an edge is clicked */\n onEdgeClick?: (edge: NetworkEdge) => void;\n /** Callback when device view changes */\n onViewChange?: (nodeId: string, view: DeviceView) => void;\n /** Callback when rack face changes */\n onRackFaceChange?: (rackId: string, face: DeviceView) => void;\n /** CSS class name */\n className?: string;\n /** Inline styles */\n style?: React.CSSProperties;\n /** If true, vertically align rack bottoms to the same baseline */\n alignRacksToBottom?: boolean;\n /** Color mode for the diagram */\n colorMode?: 'light' | 'dark' | 'system';\n /** Callback when React Flow instance is initialized */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onInit?: (instance: any) => void;\n /** Callback to get React Flow methods for save/restore */\n onFlowMethods?: (methods: { \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toObject: () => any; \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setViewport: (viewport: any) => void; \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setNodes: (nodes: any[]) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setEdges: (edges: any[]) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toImage: (options?: any) => Promise<string> \n }) => void;\n /** Show download button */\n showDownloadButton?: boolean;\n /** Download button position */\n downloadButtonPosition?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\n /** Custom download button text */\n downloadButtonText?: string;\n /** Download button styling options */\n downloadButtonStyle?: React.CSSProperties;\n /** Allow reconnecting existing edges from either end */\n allowReconnectExisting?: boolean;\n /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */\n useSmoothstepEdgesForTubes?: boolean;\n}\n\nexport * from './netbox';\n","/**\n * Power connector utilities for consistent styling across devices and PDUs\n */\n\nexport interface PowerConnectorConfig {\n type: 'C13' | 'C14' | 'C19' | 'C20';\n color: string;\n borderColor: string;\n amperage: number;\n voltage: number;\n phases: number;\n}\n\nexport const POWER_CONNECTORS: Record<string, PowerConnectorConfig> = {\n C13: {\n type: 'C13',\n color: '#f59e0b', // Orange\n borderColor: '#d97706',\n amperage: 10,\n voltage: 230,\n phases: 1\n },\n C14: {\n type: 'C14',\n color: '#f59e0b', // Orange\n borderColor: '#d97706',\n amperage: 10,\n voltage: 230,\n phases: 1\n },\n C19: {\n type: 'C19',\n color: '#fbbf24', // Amber\n borderColor: '#d97706',\n amperage: 16,\n voltage: 230,\n phases: 1\n },\n C20: {\n type: 'C20',\n color: '#fbbf24', // Amber\n borderColor: '#d97706',\n amperage: 16,\n voltage: 230,\n phases: 1\n }\n};\n\nexport interface PowerPortStyle {\n width: number;\n height: number;\n borderRadius?: string;\n clipPath?: string;\n color: string;\n borderColor: string;\n fontSize: string;\n}\n\n/**\n * Get consistent power port styling for any connector type\n */\nexport function getPowerPortStyle(connectorType: string): PowerPortStyle {\n const connector = POWER_CONNECTORS[connectorType];\n if (!connector) {\n throw new Error(`Unknown connector type: ${connectorType}`);\n }\n\n const isHighPower = connector.amperage === 16; // C19/C20 are 16A\n\n // Size: High power connectors are bigger\n const width = isHighPower ? 12 : 8; // C19/C20 bigger; C13/C14 smaller\n const height = isHighPower ? 10 : 5; // C19/C20 bigger; C13/C14 smaller\n\n // Shape: C13/C14 have chamfered corners, C19/C20 have rounded corners\n const cornerStyle = isHighPower \n ? { borderRadius: '3px' } // C19/C20: rounded corners\n : { \n clipPath: `polygon(2px 0, calc(100% - 2px) 0, 100% 2px, 100% 100%, 0 100%, 0 2px)`,\n borderRadius: '0px'\n };\n\n return {\n width,\n height,\n color: connector.color,\n borderColor: connector.borderColor,\n fontSize: isHighPower ? '3px' : '4px',\n ...cornerStyle\n };\n}\n\n/**\n * Get connector configuration by type\n */\nexport function getConnectorConfig(connectorType: string): PowerConnectorConfig {\n const connector = POWER_CONNECTORS[connectorType];\n if (!connector) {\n throw new Error(`Unknown connector type: ${connectorType}`);\n }\n return connector;\n}\n\n/**\n * Determine if a connector is high power (16A)\n */\nexport function isHighPowerConnector(connectorType: string): boolean {\n const connector = getConnectorConfig(connectorType);\n return connector.amperage === 16;\n}\n\n/**\n * Get PDU port type based on position in cycle\n * PDU cycle: [8xC13, 2xC19] = 10 ports per cycle\n */\nexport function getPDUPortType(portIndex: number): string {\n const cyclePosition = portIndex % 10; // 10 ports per cycle\n return cyclePosition < 8 ? 'C13' : 'C19';\n}\n\n/**\n * Get device connector type based on device name\n */\nexport function getDeviceConnectorType(deviceName: string): string {\n const name = deviceName.toLowerCase();\n \n // High power devices use C20\n if (name.includes('mx304') || name.includes('mx480') || name.includes('mx960')) {\n return 'C20';\n }\n \n // Standard devices use C14\n return 'C14';\n}\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode, Width, PortBlock, Port } from '../types';\nimport { U_HEIGHT_PX } from '../utils/constants';\nimport { getPowerPortStyle, getConnectorConfig, getDeviceConnectorType } from '../utils/power-connectors';\nimport { getStatusColor } from '../utils/status-colors';\n\n// Power connector styling is now handled by shared utility\n\nexport const DeviceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { \n label, \n status = 'active', \n deviceType = 'server',\n manufacturer,\n role,\n uHeight = 1,\n width = Width.FULL, // Default to full width\n ports = [], // Array of port configurations\n rearPorts = [],\n view // Optional view override\n } = data;\n\n // Determine view: prefer explicit view; if both front and rear ports exist, default to 'front'\n const currentFace = view || ((rearPorts.length > 0 && ports.length === 0) ? 'rear' : 'front');\n\n // Debug logging removed in production build; keep component silent by default\n\n // Create handle-to-side mapping for zIndex calculation\n const handleSideMap: Record<string, 'front' | 'rear'> = {};\n \n // Map ALL handles to their sides (both front and rear) for proper zIndex calculation\n // This should be independent of the current view - handles have fixed positions\n \n // Front view handles (always on front regardless of current view)\n handleSideMap['net-top'] = 'front';\n handleSideMap['net-bottom'] = 'front';\n // Add any custom front handles from ports array\n if (ports.length > 0) {\n ports.forEach(portBlock => {\n portBlock.ports.forEach(port => {\n const handleId = port.type?.includes('power') ? port.label : `${portBlock.name}-${port.label}`;\n handleSideMap[handleId] = 'front';\n });\n });\n }\n \n // Rear view handles (always on rear regardless of current view)\n handleSideMap['pwr-left-1'] = 'rear';\n handleSideMap['pwr-left-2'] = 'rear';\n handleSideMap['net-right-1'] = 'rear';\n handleSideMap['net-right-2'] = 'rear';\n // Add any custom rear handles from rearPorts array\n if (rearPorts.length > 0) {\n rearPorts.forEach(portBlock => {\n portBlock.ports.forEach(port => {\n const handleId = port.type?.includes('power') ? port.label : `${portBlock.name}-${port.label}`;\n handleSideMap[handleId] = 'rear';\n });\n });\n }\n \n\n // Removed data mutation; z-index is derived in headless selectors\n\n // Calculate device height based on U height\n const deviceHeight = uHeight * U_HEIGHT_PX;\n \n // Calculate rackDevice width based on width setting\n // Rack width is 300px, so full width = 300px, half width = 150px\n const rackDeviceWidth = width === Width.HALF ? '150px' : '304px';\n const rackDeviceLeft = width === Width.HALF ? '150px' : undefined;\n\n // Render ports from port arrays\n const renderPortsFromArray = (portBlocks: PortBlock[], position: 'front' | 'rear') => {\n const handles: React.ReactElement[] = [];\n \n if (portBlocks.length === 0) return handles;\n \n // Calculate port dimensions based on device height\n const portWidth = Math.max(4, Math.floor(deviceHeight * 0.4)); // 40% of device height, minimum 4px\n const portHeight = Math.max(2, Math.floor(deviceHeight * 0.2)); // 20% of device height, minimum 2px\n \n portBlocks.forEach((portBlock, _blockIndex) => {\n portBlock.ports.forEach((port: Port, portIndex: number) => {\n const isPower = !!port.type && port.type.includes('power');\n // Remove front-facing power connections: skip power ports on front face\n if (position === 'front' && isPower) {\n return;\n }\n const handleId = isPower ? `${port.label}` : `${portBlock.name}-${port.label}`;\n const isConnected = port.connected;\n \n // Determine port color based on type and cable medium\n let portColor = '#6b7280'; // Default grey for empty/disconnected\n if (isConnected) {\n if (port.type?.includes('power')) {\n portColor = port.type === 'power_c19' ? '#fbbf24' : '#f59e0b'; // Amber for C19, orange for C13\n } else if (port.type === 'console' || port.type === 'mgmt') {\n portColor = '#8b5cf6'; // Purple for management\n } else if (port.type === 'usb') {\n portColor = '#10b981'; // Green for USB\n } else {\n // Network port colors based on cable/transceiver type\n switch (port.cableType) {\n case 'smf': // Single Mode Fiber\n portColor = '#fbbf24'; // Yellow\n break;\n case 'cat6': // Category 6 Ethernet\n portColor = '#8b5cf6'; // Purple\n break;\n case 'om3': // OM3 Multimode Fiber\n portColor = '#06b6d4'; // Aqua/Cyan\n break;\n case 'om4': // OM4 Multimode Fiber\n portColor = '#8b5cf6'; // Violet\n break;\n case 'om5': // OM5 Multimode Fiber\n portColor = '#84cc16'; // Lime Green\n break;\n case 'cat5e': // Category 5e Ethernet\n portColor = '#3b82f6'; // Blue\n break;\n case 'cat6a': // Category 6A Ethernet\n portColor = '#ef4444'; // Red\n break;\n case 'cat7': // Category 7 Ethernet\n portColor = '#f97316'; // Orange\n break;\n case 'fiber': // Generic fiber\n portColor = '#3b82f6'; // Blue\n break;\n case 'ethernet': // Generic ethernet\n portColor = '#10b981'; // Green\n break;\n default:\n portColor = '#10b981'; // Default green for connected\n }\n }\n }\n \n // Determine position based on port type and face\n let handlePosition = Position.Top;\n let handleStyle: React.CSSProperties = {\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: isConnected ? portColor : '#6b7280',\n border: `1px solid ${isConnected ? portColor : '#374151'}`,\n borderRadius: '1px',\n cursor: 'pointer',\n };\n \n if (position === 'front') {\n // Front view: network ports on top/bottom\n if (portIndex % 2 === 0) {\n handlePosition = Position.Top;\n handleStyle.transform = 'translateY(50%)';\n handleStyle.left = `${(portIndex / 2) * (portWidth + 2)}px`;\n } else {\n handlePosition = Position.Bottom;\n handleStyle.transform = 'translateY(-50%)';\n handleStyle.left = `${((portIndex - 1) / 2) * (portWidth + 2)}px`;\n }\n } else {\n // Rear view: patch panels use same top/bottom layout as front\n // Normalize deviceType to handle both 'patch_panel' (JSON) and 'patch-panel' (code)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n if (normalizedDeviceType === 'patch-panel') {\n // Patch panel rear ports: same layout as front (top/bottom)\n if (portIndex % 2 === 0) {\n handlePosition = Position.Top;\n handleStyle.transform = 'translateY(50%)';\n handleStyle.left = `${(portIndex / 2) * (portWidth + 2)}px`;\n } else {\n handlePosition = Position.Bottom;\n handleStyle.transform = 'translateY(-50%)';\n handleStyle.left = `${((portIndex - 1) / 2) * (portWidth + 2)}px`;\n }\n } else if (port.type?.includes('power')) {\n // Power ports on left (for non-patch-panel devices)\n handlePosition = Position.Left;\n handleStyle.transform = 'translateX(50%)'; // Move inside device boundary\n // Better spacing for 1U devices - start at top and space appropriately\n const baseTop = deviceHeight <= 20 ? 10 : 20;\n const spacing = deviceHeight <= 20 ? 30 : 50;\n handleStyle.top = `${baseTop + (portIndex * spacing)}%`;\n \n // Use shared utility for consistent power port styling\n const connectorType = getDeviceConnectorType(label);\n const portStyle = getPowerPortStyle(connectorType);\n \n handleStyle = {\n ...handleStyle,\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n };\n } else {\n // Network ports on right (for non-patch-panel devices)\n handlePosition = Position.Right;\n handleStyle.transform = 'translateX(-50%)';\n handleStyle.top = `${25 + (portIndex * 50)}%`;\n }\n }\n \n // Switches and routers output connections, so their network ports should be 'source'\n // But they also need 'target' handles for switch-to-switch mesh connections\n // Patch panels route traffic bidirectionally, so they need both source and target handles\n // Servers and other devices receive connections, so their network ports should be 'target'\n // Power ports are always 'target' (devices receive power)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n let handleType: 'source' | 'target';\n if (isPower) {\n handleType = 'target';\n } else if (deviceType === 'switch' || deviceType === 'router') {\n handleType = 'source'; // Switches/routers output network connections\n // Also create a target handle for switch-to-switch mesh connections\n handles.push(\n <Handle\n key={`${handleId}-target`}\n id={`${handleId}-target`}\n type=\"target\"\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} (input) ${isConnected ? '(connected)' : '(disconnected)'}`}\n />\n );\n } else if (isPatchPanel) {\n // Patch panels route traffic bidirectionally\n // Front ports: receive from switches (target), but also need source for routing to rear\n // Rear ports: send to other patch panels (source), but also receive from other patch panels (target)\n handleType = position === 'rear' ? 'source' : 'target';\n // Always create both source and target handles for patch panels to enable routing\n const oppositeType = position === 'rear' ? 'target' : 'source';\n handles.push(\n <Handle\n key={`${handleId}-${oppositeType}`}\n id={`${handleId}-${oppositeType}`}\n type={oppositeType}\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} (${oppositeType}) ${isConnected ? '(connected)' : '(disconnected)'}`}\n />\n );\n } else {\n handleType = isConnected ? 'source' : 'target'; // Other devices receive connections by default\n }\n\n handles.push(\n <Handle\n key={handleId}\n id={handleId}\n type={handleType}\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} ${isConnected ? '(connected)' : '(disconnected)'}`}\n >\n {isPower ? portIndex + 1 : undefined}\n </Handle>\n );\n });\n });\n \n return handles;\n };\n\n // Render handles based on face orientation\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n \n // Calculate port dimensions based on device height\n const portWidth = Math.max(4, Math.floor(deviceHeight * 0.4)); // 40% of device height, minimum 4px\n const portHeight = Math.max(2, Math.floor(deviceHeight * 0.2)); // 20% of device height, minimum 2px\n \n if (currentFace === 'front') {\n // Front view\n // Front view: render from ports array if provided, else fall back to defaults\n if (ports.length > 0) {\n // Render ports from provided configuration\n return renderPortsFromArray(ports, 'front');\n }\n\n // Check if this is an AGG/core switch\n const isAGGSwitch = deviceType === 'switch' && (label.toLowerCase().includes('agg') || label.toLowerCase().includes('core') || role === 'agg' || role === 'core');\n if (isAGGSwitch) {\n return renderAGGSwitchHandles();\n }\n\n // Standard network ports on top and bottom (target - receives network from switches)\n // Standard device fallbacks\n handles.push(\n <Handle\n key=\"net-top\"\n id=\"net-top\"\n type=\"target\"\n position={Position.Top}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateY(50%)',\n }}\n title=\"Network Port (Top)\"\n />\n );\n\n handles.push(\n <Handle\n key=\"net-bottom\"\n id=\"net-bottom\"\n type=\"target\"\n position={Position.Bottom}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateY(-50%)',\n }}\n title=\"Network Port (Bottom)\"\n />\n );\n \n } else if (currentFace === 'rear') {\n // Rear view\n // Rear view: render from rearPorts array if provided, else fall back to defaults\n if (rearPorts.length > 0) {\n // Render ports from provided configuration\n return renderPortsFromArray(rearPorts, 'rear');\n }\n\n const isSwitch = deviceType === 'switch';\n // Normalize deviceType to handle both 'patch_panel' (JSON) and 'patch-panel' (code)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n\n // Power ports on left side (all devices except patch panels)\n if (!isPatchPanel) {\n // Get connector type and styling using shared utility\n const connectorType = getDeviceConnectorType(label);\n const connector = getConnectorConfig(connectorType);\n const portStyle = getPowerPortStyle(connectorType);\n\n // Power port 1 - position based on device height\n const port1Top = deviceHeight <= 20 ? '10%' : '25%'; // Start at top for 1U devices\n \n handles.push(\n <Handle\n key=\"pwr-1\"\n id=\"pwr-left-1\"\n type=\"target\"\n position={Position.Left}\n style={{\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n transform: 'translateX(50%)', // Move inside the device boundary\n top: port1Top,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port 1 (${connector.type}) - ${connector.voltage}V, ${connector.amperage}A`}\n >\n 1\n </Handle>\n );\n\n // Power port 2 - position based on device height with proper spacing\n const port2Top = deviceHeight <= 20 ? '50%' : '75%'; // Position second port lower for 1U devices\n \n handles.push(\n <Handle\n key=\"pwr-2\"\n id=\"pwr-left-2\"\n type=\"target\"\n position={Position.Left}\n style={{\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n transform: 'translateX(50%)', // Move inside the device boundary\n top: port2Top,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port 2 (${connector.type}) - ${connector.voltage}V, ${connector.amperage}A`}\n >\n 2\n </Handle>\n );\n }\n\n // Network ports on right side (for non-switch, non-patch-panel devices)\n if (!isSwitch && !isPatchPanel) {\n handles.push(\n <Handle\n key=\"net-right-1\"\n id=\"net-right-1\"\n type=\"target\"\n position={Position.Right}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateX(-50%)',\n top: '25%',\n }}\n title=\"Network Port 1 (Right)\"\n />\n );\n\n handles.push(\n <Handle\n key=\"net-right-2\"\n id=\"net-right-2\"\n type=\"target\"\n position={Position.Right}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateX(-50%)',\n top: '75%',\n }}\n title=\"Network Port 2 (Right)\"\n />\n );\n }\n }\n\n return handles;\n };\n\n // Render AGG switch handles: 48 ports on front, 4 uplinks on right\n const renderAGGSwitchHandles = () => {\n // AGG/core switch ports and uplinks\n const handles: React.ReactElement[] = [];\n \n // Calculate port dimensions - middle size for good visibility\n const portWidth = Math.max(10, Math.floor(deviceHeight * 0.45)); // 45% of device height, minimum 10px\n const portHeight = Math.max(5, Math.floor(deviceHeight * 0.25)); // 25% of device height, minimum 5px\n \n // 32 ports arranged in grid pattern: 16 on top, 16 on bottom\n // Create 32 front ports\n \n // Top row: 16 ports\n for (let i = 1; i <= 16; i++) {\n const handle = (\n <Handle\n key={`port-${i}`}\n id={`port-${i}`}\n type=\"source\"\n position={Position.Top}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '1px solid #059669', // Thinner border for cleaner look\n borderRadius: '2px',\n cursor: 'pointer',\n transform: 'translateY(50%)', // Pull handle into node\n zIndex: 1000,\n // Position ports across the top edge\n left: `${(i - 1) * (portWidth + 2)}px`, // Space ports across the width\n }}\n title={`Port ${i}`}\n />\n );\n \n \n \n handles.push(handle);\n }\n \n // Bottom row: 16 ports\n for (let i = 17; i <= 32; i++) {\n const bottomIndex = i - 16; // 1-16 for bottom row positioning\n const handle = (\n <Handle\n key={`port-${i}`}\n id={`port-${i}`}\n type=\"source\"\n position={Position.Bottom}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '1px solid #059669', // Thinner border for cleaner look\n borderRadius: '2px',\n cursor: 'pointer',\n transform: 'translateY(-50%)', // Pull handle into node\n zIndex: 1000,\n // Position ports across the bottom edge\n left: `${(bottomIndex - 1) * (portWidth + 2)}px`, // Space ports across the width\n }}\n title={`Port ${i}`}\n />\n );\n \n \n \n handles.push(handle);\n }\n \n // 4 uplink ports on the right edge (larger, different color)\n for (let i = 1; i <= 4; i++) {\n const uplinkWidth = Math.max(4, Math.floor(deviceHeight * 0.3)); // Larger uplink ports\n const uplinkHeight = Math.max(3, Math.floor(deviceHeight * 0.15)); // Taller uplink ports\n \n handles.push(\n <Handle\n key={`uplink-${i}`}\n id={`uplink-${i}`}\n type=\"source\"\n position={Position.Right}\n style={{\n width: `${uplinkWidth}px`,\n height: `${uplinkHeight}px`,\n background: '#8b5cf6', // Purple color for uplinks\n border: '0.5px solid #7c3aed',\n borderRadius: '0.5px',\n cursor: 'pointer',\n transform: 'translateX(-50%)', // Pull handle into node\n }}\n title={`Uplink ${i}`}\n />\n );\n }\n\n return handles;\n };\n\n return (\n <div\n className={`device-node ${selected ? 'selected' : ''}`}\n style={{\n background: '#1f2937',\n border: `1px solid ${getStatusColor(status)}`,\n borderRadius: '2px',\n padding: '0px', // Remove padding to fix alignment\n width: rackDeviceWidth, // Width based on width setting\n ...(rackDeviceLeft && { left: rackDeviceLeft }), // Only set left for HALF width rackDevices\n height: `${deviceHeight}px`, // Exact U height (20px per U)\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '8px',\n boxShadow: selected ? '0 0 0 1px #3b82f6' : '0 1px 2px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n cursor: 'grab',\n marginBottom: '0px', // No gap - devices should be exactly U height\n boxSizing: 'border-box',\n marginTop: '0px',\n marginLeft: '0px',\n marginRight: '0px',\n }}\n >\n {/* Standard handles are now always rendered */}\n \n {/* U Position will be calculated dynamically based on position */}\n \n \n <div style={{ \n textAlign: 'center', \n flex: 1, \n display: 'flex', \n flexDirection: 'column', \n justifyContent: 'center',\n overflow: 'hidden',\n padding: '2px', // Add small padding for text readability\n }}>\n <div style={{ \n fontWeight: 'bold', \n fontSize: '7px',\n lineHeight: '1.1',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {label}\n </div>\n {uHeight > 1 && (\n <div style={{ \n fontSize: '6px', \n color: '#9ca3af',\n lineHeight: '1',\n }}>\n {manufacturer}\n </div>\n )}\n </div>\n \n {/* U Height indicator */}\n {uHeight > 1 && (\n <div\n style={{\n position: 'absolute',\n bottom: '1px',\n right: '1px',\n background: '#374151',\n color: '#9ca3af',\n padding: '1px 2px',\n borderRadius: '1px',\n fontSize: '6px',\n lineHeight: '1',\n }}\n >\n {uHeight}U\n </div>\n )}\n \n {/* Status indicator */}\n <div\n style={{\n position: 'absolute',\n bottom: '1px',\n left: '1px',\n width: '4px',\n height: '4px',\n background: getStatusColor(status),\n borderRadius: '50%',\n }}\n />\n \n {/* React Flow edge handles based on face orientation */}\n {renderHandles()}\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\nimport { getPowerPortStyle, getPDUPortType } from '../utils/power-connectors';\n\nexport enum MgmtUnitPosition {\n TOP = 'top',\n MIDDLE = 'middle',\n BOTTOM = 'bottom'\n}\n\nexport const VerticalPDU: React.FC<NodeProps<NetworkNode['data']>> = ({\n data,\n selected,\n}) => {\n const {\n label,\n status = 'active',\n heightCm = 100,\n powerPorts = 36, // Default number of AC power ports (10 C13 + 2 C19) × 3\n widthPx = 15,\n mgmt_unit, // Optional management unit position\n } = data;\n\n // Convert cm to pixels (1cm = 4.2px)\n const heightPx = heightCm * 4.2;\n\n // Completely custom vertical positioning for C13/C19/sets\n const renderPowerHandles = () => {\n // CYCLE = [8xC13, 2xC19], three times (for 30 ports)\n // Strategy:\n // - Use minimal/gapless \"start\" offset (header), so first port right beneath header.\n // - C13 ports: minimal gap (tight)\n // - C19 ports: even tighter gap than C13 (or zero)\n // - After last C19 of set: add a MUCH bigger gap before the new cycle (visual break).\n // - Ensure total height, including all ports and gaps, fits exactly into the available drawing area, and cycles are visually distinct.\n const cycleLength = 10; // 8 C13, 2 C19\n const nCycles = Math.ceil(powerPorts / cycleLength);\n const portsPerCycle = Array(cycleLength).fill(0).map((_, i) => (i < 8 ? '10A' : '16A'));\n\n // Sizing\n const C13_HEIGHT = 5;\n const C19_HEIGHT = 7;\n\n // Build metadata of port types and port heights\n const portMeta = [];\n for (let c = 0, idx = 0; c < nCycles; ++c) {\n for (let i = 0; i < cycleLength && idx < powerPorts; ++i, ++idx) {\n const portType = portsPerCycle[i];\n const is16A = portType === '16A';\n portMeta.push({\n portType,\n is16A,\n idx,\n isLastInCycle: i === cycleLength - 1,\n // For gap calculation\n isC19: is16A,\n portHeight: is16A ? C19_HEIGHT : C13_HEIGHT,\n });\n }\n }\n\n // Calculate the \"cycle\" indices (where to add the larger cycle gap)\n const handles = [];\n // Account for header height (20px) and add minimal padding\n const headerHeight = 15;\n const availableHeight = heightPx - headerHeight - 3; // 5px padding at bottom\n\n // REDUCE vertical spacing: 30% less spacing between ports\n // So multiply the calculated spacing by 0.7\n const rawPortSpacing = availableHeight / (powerPorts - 9);\n const portSpacing = rawPortSpacing * 0.5; // Even tighter spacing\n \n for (let i = 0; i < powerPorts; i++) {\n const yPos = headerHeight - 2 + (portSpacing * i); // Start slightly above header\n const handleId = `${i + 1}`;\n \n // Check if this position should be the management unit\n const isMgmtPosition = mgmt_unit && (\n (mgmt_unit === 'top' && i === 0) ||\n (mgmt_unit === 'middle' && i === Math.floor(powerPorts / 2)) ||\n (mgmt_unit === 'bottom' && i === powerPorts - 1)\n );\n \n if (isMgmtPosition) {\n handles.push(renderMgmtUnit(yPos));\n continue;\n }\n \n // Get port type and styling using shared utility\n const portType = getPDUPortType(i);\n const portStyle = getPowerPortStyle(portType);\n \n // Fix: Center the port more accurately (add -1px shift for visual center).\n const leftPx = Math.round((widthPx - portStyle.width) / 2 -1) ;\n\n handles.push(\n <Handle\n key={`handle-${handleId}`}\n type=\"source\"\n position={Position.Right}\n id={handleId}\n style={{\n position: 'absolute',\n left: `${leftPx}px`,\n top: `${yPos - (portStyle.height / 2)}px`,\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port ${i + 1} (${portType})`}\n >\n {i + 1}\n </Handle>\n );\n }\n return handles;\n };\n\n // Render management unit as a power port in the sequence\n const renderMgmtUnit = (yPos: number) => {\n const mgmtWidth = 16;\n const mgmtHeight = 12;\n\n return (\n <div\n key=\"mgmt-unit\"\n style={{\n position: 'absolute',\n left: `${(widthPx - mgmtWidth) / 2}px`,\n top: `${yPos - (mgmtHeight / 2)}px`,\n width: `${mgmtWidth}px`,\n height: `${mgmtHeight}px`,\n background: '#1a1a1a',\n border: '1px solid #374151',\n borderRadius: '1px',\n display: 'flex',\n flexDirection: 'column',\n padding: '1px',\n zIndex: 10,\n }}\n >\n {/* Screen positioned on the left */}\n <div\n style={{\n position: 'absolute',\n left: '-10px',\n top: '1px',\n background: '#ffffff',\n border: '0.5px solid #6b7280',\n borderRadius: '0.5px',\n width: '8px',\n height: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '3px',\n color: '#10b981',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n transform: 'rotate(90deg)',\n transformOrigin: 'center',\n }}\n >\n APC\n </div>\n \n {/* Single Network Port Handle */}\n <Handle\n key=\"mgmt-net-1\"\n type=\"source\"\n position={Position.Right}\n id=\"mgmt-net-1\"\n style={{\n width: '70%',\n height: '6px',\n background: '#10b981',\n border: '1px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n zIndex: 11,\n margin: '0 auto',\n }}\n title=\"Management Network Port\"\n />\n </div>\n );\n };\n\n return (\n <div\n className={`vertical-pdu-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'linear-gradient(90deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n border: `1px solid ${getStatusColor(status)}`,\n borderRadius: '2px',\n padding: 0,\n width: `${widthPx}px`,\n height: `${heightPx}px`,\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 1px 3px rgba(0,0,0,0.3)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n \n {/* PDU Header */}\n <div style={{ \n textAlign: 'center', \n marginBottom: 0, \n zIndex: 2, \n background: 'linear-gradient(90deg, #4a5568 0%, #2d3748 50%, #4a5568 100%)', \n padding: '2px',\n position: 'relative',\n height: '20px',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n borderBottom: '1px solid #4a5568',\n }}>\n <div style={{ fontWeight: 'bold', fontSize: '6px', color: '#e2e8f0' }}>{label}</div>\n </div>\n \n {/* PDU Body with power ports */}\n <div\n style={{\n flex: 1,\n background: 'linear-gradient(180deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n position: 'relative',\n minHeight: `${heightPx - 20}px`,\n overflow: 'hidden',\n }}\n >\n {renderPowerHandles()}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps, useReactFlow, useEdges, Edge } from 'reactflow';\nimport { NetworkNode, NetworkEdge } from '../types';\n\nexport const SpliceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { lossDb } = data || {};\n // Use useEdges hook to subscribe to edge changes - this will cause re-render when edges change\n const edges = useEdges<NetworkEdge>();\n \n // Get colors from connected edges, not from node data\n // Left handle can receive connections (target)\n const leftEdge = edges.find((e: Edge<NetworkEdge>) => e.target === id && e.targetHandle === 'left') as NetworkEdge | undefined;\n // Right handle can both send (source) and receive (target) connections\n const rightEdgeAsSource = edges.find((e: Edge<NetworkEdge>) => e.source === id && e.sourceHandle === 'right') as NetworkEdge | undefined;\n const rightEdgeAsTarget = edges.find((e: Edge<NetworkEdge>) => e.target === id && e.targetHandle === 'right') as NetworkEdge | undefined;\n const rightEdge = rightEdgeAsSource || rightEdgeAsTarget;\n \n // Get color from edge data, or use default gray if no edge\n const leftColor = leftEdge?.data?.color || '#555';\n const rightColor = rightEdge?.data?.color || '#555';\n \n // Only show glow when both handles are connected\n const bothConnected = !!leftEdge && !!rightEdge;\n\n return (\n <div\n className={`splice-node ${selected ? 'selected' : ''}`}\n style={{\n width: 69,\n height: 16,\n borderRadius: 8,\n border: 'none',\n outline: 'none',\n position: 'relative',\n background: 'transparent',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : 'none',\n }}\n >\n {/* Split background showing both colors with opacity for text readability */}\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n borderRadius: 8,\n overflow: 'hidden',\n opacity: 0.75,\n pointerEvents: 'none', // Don't block handles\n }}\n >\n <div style={{ background: leftColor }} />\n <div style={{ background: rightColor }} />\n </div>\n \n {/* Overlay with blur and opacity to make text clearer - respects dark/light mode */}\n <div\n className=\"splice-text-overlay\"\n style={{\n position: 'absolute',\n inset: 0,\n borderRadius: 8,\n pointerEvents: 'none',\n zIndex: 1,\n }}\n />\n \n {/* Thin glow line at the weld junction - only when both handles are connected */}\n {bothConnected && (\n <div\n className=\"splice-glow\"\n style={{\n position: 'absolute',\n left: '50%',\n top: 0,\n bottom: 0,\n width: '1px',\n background: 'rgba(255, 255, 255, 0.6)',\n boxShadow: '0 0 2px rgba(255, 255, 255, 0.8), 0 0 4px rgba(255, 255, 255, 0.4)',\n pointerEvents: 'none',\n zIndex: 2,\n }}\n />\n )}\n \n {/* Loss value label - only show when both handles are connected */}\n {bothConnected && typeof lossDb === 'number' && (\n <div\n className=\"splice-text-label animate-in\"\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 9,\n fontFamily: 'monospace',\n pointerEvents: 'none',\n zIndex: 3,\n fontWeight: 'bold',\n }}\n >\n {`${lossDb.toFixed(2)} dB`}\n </div>\n )}\n \n {/* Left handle (target) - receives connections - only one connection allowed */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"left\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: leftColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n left: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n \n {/* Right handle (source) - sends connections - only one connection allowed */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"right\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: rightColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n right: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n \n {/* Right handle (target) - receives connections - only one connection allowed */}\n <Handle\n type=\"target\"\n position={Position.Right}\n id=\"right\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: rightColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n right: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n </div>\n );\n};\n","import { NetworkNode } from '../types';\nimport { RACK_HEADER_HEIGHT } from './constants';\n\n/**\n * Height of each holder position in pixels (one splice per holder)\n */\nexport const HOLDER_HEIGHT_PX = 20;\n\n/**\n * Tray header height in pixels (matches RACK_HEADER_HEIGHT)\n */\nexport const TRAY_HEADER_HEIGHT = 32;\n\n/**\n * Bottom padding for tray in pixels\n */\nexport const TRAY_BOTTOM_PADDING = 4;\n\n/**\n * Number of holders per tray (12f per tray)\n */\nexport const HOLDERS_PER_TRAY = 12;\n\n/**\n * Splice width in pixels (must match SpliceNode width)\n */\nexport const SPLICE_WIDTH_PX = 69;\n\n/**\n * Tray width in pixels (narrower to fit splice properly)\n */\nexport const TRAY_WIDTH_PX = 80;\n\n/**\n * Fixed X position to center splices within tray content\n */\nexport const SPLICE_CENTER_X = (TRAY_WIDTH_PX - SPLICE_WIDTH_PX) / 2;\n\n/**\n * Calculate holder position from Y coordinate within a tray\n */\nexport const calculateHolderPositionFromY = (\n tray: NetworkNode,\n y: number\n): number => {\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = y - startY;\n const holderPosition = Math.round(relativeY / HOLDER_HEIGHT_PX) + 1;\n const maxHolders = HOLDERS_PER_TRAY;\n return Math.max(1, Math.min(maxHolders, holderPosition));\n};\n\n/**\n * Snap a splice to the nearest holder position within a tray\n */\nexport const snapToSplicePosition = (\n splice: NetworkNode,\n tray: NetworkNode,\n newPosition: { x: number; y: number },\n allNodes: NetworkNode[]\n): { x: number; y: number; holderPosition?: number } => {\n if (!splice.parentId || splice.parentId !== tray.id) {\n return newPosition;\n }\n\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = newPosition.y - startY;\n const calculatedPosition = Math.round(relativeY / HOLDER_HEIGHT_PX) + 1;\n const maxPosition = HOLDERS_PER_TRAY;\n const snappedPosition = Math.max(1, Math.min(maxPosition, calculatedPosition));\n\n // Check if position is available\n if (!isHolderPositionAvailable(tray, splice, snappedPosition, allNodes)) {\n const availablePosition = findNextAvailableHolderPosition(tray, splice, allNodes, snappedPosition);\n if (availablePosition !== snappedPosition) {\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: startY + (availablePosition - 1) * HOLDER_HEIGHT_PX + baseOffset,\n holderPosition: availablePosition,\n };\n }\n }\n\n // Snap to exact holder position, left aligned x\n const spliceHeight = 16; // Splice height in pixels\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n const snappedY = startY + (snappedPosition - 1) * HOLDER_HEIGHT_PX + baseOffset;\n\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: snappedY,\n holderPosition: snappedPosition,\n };\n};\n\n/**\n * Check if a holder position is available in a tray\n */\nexport const isHolderPositionAvailable = (\n tray: NetworkNode,\n splice: NetworkNode,\n position: number,\n allNodes: NetworkNode[]\n): boolean => {\n const trayChildren = allNodes.filter(\n (n) => n.parentId === tray.id && n.type === 'splice' && n.id !== splice.id\n );\n\n return !trayChildren.some((child) => {\n const childPosition = (child.data as NetworkNode['data']).holderPosition;\n return childPosition === position;\n });\n};\n\n/**\n * Find the next available holder position\n */\nexport const findNextAvailableHolderPosition = (\n tray: NetworkNode,\n splice: NetworkNode,\n allNodes: NetworkNode[],\n startFrom: number = 1\n): number => {\n for (let pos = startFrom; pos <= HOLDERS_PER_TRAY; pos++) {\n if (isHolderPositionAvailable(tray, splice, pos, allNodes)) {\n return pos;\n }\n }\n\n // Try positions before startFrom\n for (let pos = startFrom - 1; pos >= 1; pos--) {\n if (isHolderPositionAvailable(tray, splice, pos, allNodes)) {\n return pos;\n }\n }\n\n return 1; // Fallback to position 1\n};\n\n/**\n * Calculate splice position based on holder number within a tray\n */\nexport const calculateSplicePositionFromNumber = (\n tray: NetworkNode,\n holderPosition: number\n): { x: number; y: number } => {\n const startY = TRAY_HEADER_HEIGHT;\n // Position splice in holder slot (HOLDER_HEIGHT_PX = 20, splice height = 16)\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n const spliceY = startY + (holderPosition - 1) * HOLDER_HEIGHT_PX + baseOffset;\n\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: spliceY,\n };\n};\n","import React, { useState } from 'react';\nimport { NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { TRAY_HEADER_HEIGHT, HOLDER_HEIGHT_PX, HOLDERS_PER_TRAY, TRAY_WIDTH_PX, TRAY_BOTTOM_PADDING } from '../utils/splice-positioning';\n\nexport const SpliceTrayNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { label = 'Splice Tray', status = 'active' } = data || {};\n const [showHolderMarkers, setShowHolderMarkers] = useState(false);\n\n // Generate holder position markers (like U markers in racks)\n const renderHolderPositions = () => {\n if (!showHolderMarkers) return null;\n const positions = [];\n const startY = TRAY_HEADER_HEIGHT;\n\n for (let i = 1; i <= HOLDERS_PER_TRAY; i++) {\n const yPos = startY + (i - 1) * HOLDER_HEIGHT_PX;\n\n positions.push(\n <div\n key={i}\n style={{\n position: 'absolute',\n left: '-35px',\n top: `${yPos}px`,\n background: '#374151',\n color: '#9ca3af',\n padding: '2px 4px',\n borderRadius: '2px',\n fontSize: '8px',\n fontWeight: 'bold',\n width: '28px',\n textAlign: 'center',\n border: '1px solid #4b5563',\n zIndex: 10,\n height: `${HOLDER_HEIGHT_PX}px`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n >\n H{i}\n </div>\n );\n }\n return positions;\n };\n\n return (\n <div\n className={`splice-tray-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'transparent',\n border: 'none',\n borderRadius: '8px',\n padding: 0,\n width: `${TRAY_WIDTH_PX}px`, // Width to accommodate splice\n height: `${TRAY_HEADER_HEIGHT + HOLDERS_PER_TRAY * HOLDER_HEIGHT_PX + TRAY_BOTTOM_PADDING}px`, // Header + holder area + bottom padding\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected\n ? '0 0 0 2px #3b82f6'\n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* Tray Header */}\n <div\n style={{\n textAlign: 'center',\n marginBottom: 0,\n zIndex: 2,\n background: '#1f2937',\n padding: '2px',\n position: 'relative',\n height: `${TRAY_HEADER_HEIGHT}px`,\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '6px',\n borderRadius: '8px',\n }}\n >\n <div style={{ fontWeight: 'bold', fontSize: '10px' }}>{label}</div>\n <button\n onPointerDown={(e) => {\n e.stopPropagation();\n }}\n onMouseDown={(e) => {\n e.stopPropagation();\n }}\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n setShowHolderMarkers(!showHolderMarkers);\n }}\n style={{\n background: showHolderMarkers ? '#10b981' : '#374151',\n color: showHolderMarkers ? '#ffffff' : '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`${showHolderMarkers ? 'Hide' : 'Show'} holder markers`}\n >\n H\n </button>\n </div>\n\n {/* Holder position markers */}\n {renderHolderPositions()}\n\n {/* Content area where SpliceNode children will be placed */}\n <div\n style={{\n position: 'absolute',\n top: TRAY_HEADER_HEIGHT,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n }}\n />\n </div>\n );\n};\n","import React from 'react';\n\n/**\n * TIA-598-C standard fiber optic color codes (12 base colors)\n * Colors 1-12: Blue, Orange, Green, Brown, Slate, White, Red, Black, Yellow, Violet, Rose, Aqua\n * @public\n */\nexport const FIBER_COLORS_12 = [\n '#1f77b4', /* Blue */\n '#ff7f0e', /* Orange */\n '#2ca02c', /* Green */\n '#8c564b', /* Brown */\n '#708090', /* Slate */\n '#ffffff', /* White */\n '#d62728', /* Red */\n '#000000', /* Black */\n '#ffdf00', /* Yellow */\n '#8a2be2', /* Violet */\n '#ff69b4', /* Rose */\n '#00ffff' /* Aqua */\n] as const;\n\n/**\n * Fiber color ID type (1-24)\n * @public\n */\nexport type FiberColorId = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24;\n\n/**\n * Get the base color for a fiber color ID\n * Colors 13-24 use the same base colors as 1-12\n * @param id - Fiber color ID (1-24)\n * @returns Hex color code\n * @public\n */\nexport function baseColorFor(id: FiberColorId | number): string {\n const normalizedId = ((id - 1) % 12);\n return FIBER_COLORS_12[normalizedId];\n}\n\n/**\n * Check if a fiber color ID uses a striped pattern (13-24)\n * @param id - Fiber color ID (1-24)\n * @returns True if the color should be striped\n * @public\n */\nexport function isStriped(id: FiberColorId | number): boolean {\n return id > 12;\n}\n\n/**\n * Get CSS properties for a fiber color (solid or striped)\n * Colors 13-24 use a black stripe pattern over the base color\n * @param id - Fiber color ID (1-24)\n * @returns CSS properties for the color\n * @public\n */\nexport function fiberSolidOrStriped(id: FiberColorId | number): React.CSSProperties {\n const base = baseColorFor(id);\n if (isStriped(id)) {\n return {\n background: base,\n backgroundImage: `repeating-linear-gradient(45deg, ${base} 0 6px, #000 6px 9px)`,\n };\n }\n return { background: base };\n}\n\n/**\n * Get the hex color code for a fiber color ID\n * @param id - Fiber color ID (1-24)\n * @returns Hex color code\n * @public\n */\nexport function getFiberColor(id: FiberColorId | number): string {\n return baseColorFor(id);\n}\n\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { fiberSolidOrStriped, baseColorFor } from '../utils/fiber-colors';\n\n/**\n * TubeNode\n * - Rectangular node representing a buffer tube (horizontal orientation, rotated 180 degrees)\n * - Renders 12 or 24 fiber handles on the top side with TIA-598 colors\n * - Tube border tinted by tube index color (1..12 cycling)\n * - startOn parameter controls handle positioning:\n * - 'left-center' (default): handles centered on top, tube handle on bottom\n * - 'left': handles on left side, tube handle on left\n * - 'right': handles on right side with reversed colors, tube handle on right\n */\nexport const TubeNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { fibersPerTube = 12, tubeIndex = 1, startOn = 'left-center' } = data || {};\n\n // Calculate dimensions - rectangle that fits all fibers horizontally (rotated 90 degrees to be flat)\n const fibers = Math.max(1, Math.min(24, Number(fibersPerTube) || 12));\n const handleSize = 14; // Handle size\n const handleSpacing = 4;\n const padding = 1; // Reduced padding to make tube thinner\n const borderWidth = 2; // Thinner border\n // Height must accommodate: border (2px * 2) + padding (1px * 2) + handle (14px) = 20px\n const height = 20; // Thinner tube but still fits handles inside and centered\n const totalHandlesWidth = (fibers * handleSize) + ((fibers - 1) * handleSpacing);\n const width = Math.max(60, totalHandlesWidth + (padding * 2) + (borderWidth * 2));\n\n const tubeBorderColor = baseColorFor(((tubeIndex - 1) % 12) + 1);\n const tubeConnectionHandleId = `tube-${tubeIndex}`;\n const tubeConnectionHandleSize = 18; // Larger handle for easier grabbing\n const connectionHandleStyle: React.CSSProperties & { '--fiber-bg'?: string } = {\n width: tubeConnectionHandleSize,\n height: tubeConnectionHandleSize,\n borderRadius: '50%',\n opacity: 0.25, // Visible but subtle\n pointerEvents: 'auto',\n background: tubeBorderColor,\n backgroundColor: tubeBorderColor,\n border: `2px solid ${tubeBorderColor}`,\n '--fiber-bg': tubeBorderColor,\n };\n\n // Determine tube connection handle position based on startOn\n const getTubeConnectionPosition = () => {\n if (startOn === 'left') return Position.Left;\n if (startOn === 'right') return Position.Right;\n return Position.Bottom; // default 'left-center'\n };\n\n // Render handles based on startOn mode\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n const innerWidth = width - (borderWidth * 2) - (padding * 2);\n const innerHeight = height - (borderWidth * 2) - (padding * 2);\n \n let startLeft: number;\n let handlePosition: Position;\n let reverseColors = false;\n \n if (startOn === 'left') {\n // Handles start from left (not centered), positioned on top\n startLeft = padding;\n handlePosition = Position.Top;\n } else if (startOn === 'right') {\n // Handles start from right, positioned on top, colors reversed\n startLeft = padding + innerWidth - totalHandlesWidth;\n handlePosition = Position.Top;\n reverseColors = true;\n } else {\n // Default 'left-center': handles centered on top\n startLeft = padding + (innerWidth - totalHandlesWidth) / 2;\n handlePosition = Position.Top;\n }\n \n for (let i = 0; i < fibers; i++) {\n // Calculate fiber index - reverse if startOn is 'right'\n const fiberIdx = reverseColors ? (fibers - i) : (i + 1);\n const fiberStyle = fiberSolidOrStriped(fiberIdx);\n const baseColor = baseColorFor(fiberIdx);\n \n // Position handles on top, horizontally arranged\n const left = startLeft + (i * (handleSize + handleSpacing));\n const top = padding;\n\n // Build handle style with fiber color\n const handleBackground = fiberStyle.backgroundImage \n ? fiberStyle.backgroundImage\n : baseColor;\n\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n left: `${left}px`,\n top: `${top}px`,\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n border: 'none',\n background: handleBackground,\n backgroundColor: baseColor,\n zIndex: 10,\n cursor: 'pointer',\n '--fiber-bg': baseColor,\n };\n \n // Set background image variable if there is one\n if (fiberStyle.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberStyle.backgroundImage;\n }\n\n const fiberHandleId = `fiber-${fiberIdx}`;\n\n handles.push(\n <React.Fragment key={`fiber-${fiberIdx}`}>\n {/* Target handle - only one connection allowed */}\n <Handle\n id={fiberHandleId}\n type=\"target\"\n position={handlePosition}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={fiberIdx}\n data-fiber-color={baseColor}\n />\n {/* Source handle (overlapped to allow connect from either side) - only one connection allowed */}\n <Handle\n id={fiberHandleId}\n type=\"source\"\n position={handlePosition}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={fiberIdx}\n data-fiber-color={baseColor}\n />\n </React.Fragment>\n );\n }\n \n return handles;\n };\n\n return (\n <div\n style={{\n width: width,\n height: height,\n borderRadius: 4,\n background: '#111827',\n border: `${borderWidth}px solid ${selected ? '#3b82f6' : tubeBorderColor}`,\n position: 'relative',\n boxShadow: selected ? `0 0 0 ${borderWidth}px #3b82f6` : '0 2px 4px rgba(0,0,0,0.2)',\n padding: padding,\n boxSizing: 'border-box',\n }}\n >\n {/* Render fiber handles */}\n {renderHandles()}\n {/* Hidden handle for cable-to-tube connections - position depends on startOn */}\n <Handle\n id={tubeConnectionHandleId}\n type=\"target\"\n position={getTubeConnectionPosition()}\n isConnectable={true}\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n />\n <Handle\n id={tubeConnectionHandleId}\n type=\"source\"\n position={getTubeConnectionPosition()}\n isConnectable={true}\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n />\n </div>\n );\n};\n\n\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { fiberSolidOrStriped, baseColorFor } from '../utils/fiber-colors';\n\n/**\n * CableNode\n * - Visually mirrors TubeNode but represents an entire cable\n * - Each colored handle corresponds to a tube within the cable\n * - Displays cable summary text (fiber count + cable identifier)\n */\nexport const CableNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const {\n tubeCount = 12,\n fibersPerTube = 12,\n fiberCount: providedFiberCount,\n cableId = 'CBL-002',\n label,\n tubeStartIndex: rawTubeStartIndex = 1,\n borderStyle = 'default', // 'default', 'black', 'black-yellow-striped'\n } = data || {};\n\n const tubes = Math.max(1, Math.min(24, Number(tubeCount) || 12));\n const tubeStartIndex = Math.max(1, Number(rawTubeStartIndex) || 1);\n const handleSize = 8;\n const handleSpacing = 2;\n const padding = 6;\n const innerPaddingTop = padding + handleSize + 4;\n const height = 60;\n const width = Math.max(120, (tubes * (handleSize + handleSpacing)) + (padding * 2));\n const totalFibers = providedFiberCount ?? tubes * (Number(fibersPerTube) || 12);\n\n const primaryText = label ?? `${totalFibers}f Cable`;\n const secondaryText = cableId ? `Cable ID ${cableId}` : undefined;\n const firstTubeColor = baseColorFor(tubeStartIndex);\n \n // Determine border color/style based on borderStyle prop\n let borderColor = selected ? '#3b82f6' : firstTubeColor;\n let useStripedBorder = false;\n \n if (borderStyle === 'black') {\n borderColor = selected ? '#3b82f6' : '#000000';\n } else if (borderStyle === 'black-yellow-striped') {\n borderColor = selected ? '#3b82f6' : '#000000';\n useStripedBorder = !selected;\n }\n\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n\n for (let i = 0; i < tubes; i++) {\n const tubeIdx = tubeStartIndex + i;\n const tubeStyle = fiberSolidOrStriped(tubeIdx);\n const baseColor = baseColorFor(tubeIdx);\n\n const left = padding + (i * (handleSize + handleSpacing));\n const top = -(handleSize / 2);\n\n const handleBackground = tubeStyle.backgroundImage ? tubeStyle.backgroundImage : baseColor;\n\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n left: `${left}px`,\n top: `${top}px`,\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n border: 'none',\n background: handleBackground,\n backgroundColor: baseColor,\n zIndex: 10,\n cursor: 'pointer',\n '--fiber-bg': baseColor,\n };\n\n if (tubeStyle.backgroundImage) {\n handleStyle['--fiber-bg-image'] = tubeStyle.backgroundImage;\n }\n\n const tubeHandleId = `tube-${tubeIdx}`;\n\n handles.push(\n <React.Fragment key={`tube-${tubeIdx}`}>\n <Handle\n id={tubeHandleId}\n type=\"target\"\n position={Position.Top}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={tubeIdx}\n data-tube-idx={tubeIdx}\n data-tube-color={baseColor}\n />\n <Handle\n id={tubeHandleId}\n type=\"source\"\n position={Position.Top}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={tubeIdx}\n data-tube-idx={tubeIdx}\n data-tube-color={baseColor}\n />\n </React.Fragment>\n );\n }\n\n return handles;\n };\n\n const borderWidth = 2;\n const innerContent = (\n <div\n style={{\n width: '100%',\n height: '100%',\n borderRadius: useStripedBorder ? 2 : 4,\n background: '#111827',\n position: 'relative',\n padding: padding,\n paddingTop: innerPaddingTop,\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n textAlign: 'center',\n gap: 2,\n }}\n >\n {renderHandles()}\n <div style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>\n {primaryText}\n </div>\n {secondaryText && (\n <div style={{ fontSize: 10, opacity: 0.8 }}>\n {secondaryText}\n </div>\n )}\n </div>\n );\n\n // If using striped border, wrap in an outer div with striped background\n if (useStripedBorder) {\n return (\n <div\n style={{\n width,\n height,\n borderRadius: 4,\n background: 'repeating-linear-gradient(45deg, #000000 0 6px, #ffdf00 6px 9px)',\n padding: borderWidth,\n boxSizing: 'border-box',\n position: 'relative',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.2)',\n }}\n >\n {innerContent}\n </div>\n );\n }\n\n // Default border style\n return (\n <div\n style={{\n width,\n height,\n borderRadius: 4,\n background: '#111827',\n border: `${borderWidth}px solid ${borderColor}`,\n position: 'relative',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.2)',\n padding: padding,\n paddingTop: innerPaddingTop,\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n textAlign: 'center',\n gap: 2,\n }}\n >\n {renderHandles()}\n <div style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>\n {primaryText}\n </div>\n {secondaryText && (\n <div style={{ fontSize: 10, opacity: 0.8 }}>\n {secondaryText}\n </div>\n )}\n </div>\n );\n};\n\n","import type { NetworkEdge, NetworkNode } from '../types';\n\nexport type ViewFace = 'front' | 'rear';\n\nexport interface NetworkDiagramState {\n nodes: NetworkNode[];\n edges: NetworkEdge[];\n debug?: boolean;\n}\n\nexport interface ValidateConnectionParams {\n source: string | null;\n target: string | null;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n}\n\nexport interface ValidationResult { valid: boolean; reason?: string }\n\nexport interface NetworkDiagramOptions {\n validateConnection?: (params: ValidateConnectionParams, ctx: NetworkDiagramState) => ValidationResult;\n}\n\nexport interface NetworkDiagramStore {\n getState: () => NetworkDiagramState;\n setState: (partial: Partial<NetworkDiagramState>) => void;\n subscribe: (listener: (state: NetworkDiagramState) => void) => () => void;\n // selectors\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n validateConnection: (params: ValidateConnectionParams) => ValidationResult;\n selectNodeById: (id: string) => NetworkNode | undefined;\n selectConnectedEdges: (nodeId: string) => NetworkEdge[];\n}\n\nfunction defaultValidateConnection(params: ValidateConnectionParams, ctx: NetworkDiagramState): ValidationResult {\n if (!params.source || !params.target || !params.sourceHandle || !params.targetHandle) return { valid: true };\n\n const sourceAlready = ctx.edges.some(e => e.source === params.source && e.sourceHandle === params.sourceHandle);\n const targetAlready = ctx.edges.some(e => e.target === params.target && e.targetHandle === params.targetHandle);\n if (sourceAlready) return { valid: false, reason: 'Source port is already connected' };\n if (targetAlready) return { valid: false, reason: 'Target port is already connected' };\n\n // Enforce basic port-type compatibility: prevent network cables into power ports (and vice versa)\n const sourceHandleId = params.sourceHandle;\n const targetHandleId = params.targetHandle;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sourceNode = ctx.nodes.find(n => n.id === params.source) as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const targetNode = ctx.nodes.find(n => n.id === params.target) as any;\n\n // Treat any power outlet handle on a PDU as power (IDs are numeric), except the explicit mgmt network port\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const isPowerHandle = (h: string, node?: any) => {\n if (!h) return false;\n const looksLikeDevicePower = h.startsWith('pwr') || h.startsWith('power');\n const isPduPower = node?.type === 'vertical-pdu' && h !== 'mgmt-net-1';\n return looksLikeDevicePower || isPduPower;\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const isNetworkHandle = (h: string, node?: any) => {\n if (!h) return false;\n if (node?.type === 'vertical-pdu' && h === 'mgmt-net-1') return true;\n // Tube fiber handles (fiber-1, fiber-2, etc.)\n if (node?.type === 'tube' && h.startsWith('fiber-')) return true;\n if ((node?.type === 'tube' || node?.type === 'cable') && h.startsWith('tube-')) return true;\n // Splice handles (left, right)\n if (node?.type === 'splice' && (h === 'left' || h === 'right')) return true;\n // Check for common network handle patterns\n const looksLikeNetwork = h.startsWith('net-') || h.startsWith('port-') || h.startsWith('uplink-') || h.includes('Fiber') || h.includes('Ports');\n // Check if this is a custom port name from port blocks (e.g., \"QSFP28-1\", \"SFP+-2\", etc.)\n // Custom port names typically follow pattern: \"BlockName-Number\" where BlockName contains port type info\n const isCustomPortName = /^[A-Z0-9]+-\\d+$/.test(h) && !h.startsWith('pwr') && !h.startsWith('power');\n return looksLikeNetwork || isCustomPortName;\n };\n\n const sourceIsPower = isPowerHandle(sourceHandleId, sourceNode);\n const targetIsPower = isPowerHandle(targetHandleId, targetNode);\n const sourceIsNetwork = isNetworkHandle(sourceHandleId, sourceNode);\n const targetIsNetwork = isNetworkHandle(targetHandleId, targetNode);\n\n // If one side is power and the other is network, reject\n if ((sourceIsPower && targetIsNetwork) || (targetIsPower && sourceIsNetwork)) {\n return { valid: false, reason: 'Cannot connect network cable to power port' };\n }\n\n // If one side is explicitly power and the other side is neither power nor network, still reject\n if ((sourceIsPower && !targetIsPower) || (targetIsPower && !sourceIsPower)) {\n return { valid: false, reason: 'Power ports must connect to power-compatible ports' };\n }\n\n // Dual-feed power rule: if a device has two power ports, they must go to different PDUs\n // Identify PDU node and Device node for this connection\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const isPduTarget = targetNode?.type === 'vertical-pdu';\n\n if (sourceIsPower || targetIsPower) {\n const deviceNode = isPduSource ? targetNode : isPduTarget ? sourceNode : null;\n const pduNode = isPduSource ? sourceNode : isPduTarget ? targetNode : null;\n\n // Only enforce if we can identify both sides (PDU <-> device)\n if (deviceNode && pduNode) {\n // Find existing power edges connected to this device\n const devicePowerEdges = ctx.edges.filter(e => {\n const eSourceIsPower = isPowerHandle(e.sourceHandle || '');\n const eTargetIsPower = isPowerHandle(e.targetHandle || '');\n const involvesDevice = e.source === deviceNode.id || e.target === deviceNode.id;\n return (eSourceIsPower || eTargetIsPower) && involvesDevice;\n });\n\n // If there is already a power edge to this device from the same PDU, reject\n const samePduAlready = devicePowerEdges.some(e => e.source === pduNode.id || e.target === pduNode.id);\n if (samePduAlready) {\n // If device has more than one power handle, enforce connecting to the other PDU\n return { valid: false, reason: 'Dual-feed required: connect second power to a different PDU' };\n }\n }\n }\n\n return { valid: true };\n}\n\n// Determine which face a given handle belongs to, based on node data\nexport function getHandleSide(handleId: string, node: NetworkNode | undefined): ViewFace | undefined {\n if (!node) return undefined;\n // Normalize React Flow bidirectional handle suffixes used by patch panels\n // e.g. \"Rear Ports-1-target\" -> \"Rear Ports-1\"\n const normalizedHandleId = typeof handleId === 'string'\n ? handleId.replace(/-(target|source)$/i, '')\n : handleId;\n const data = node.data ?? {};\n\n // Check handleSideMap first if available\n const handleSideMap = (data as { handleSideMap?: Record<string, ViewFace> }).handleSideMap;\n if (handleSideMap && handleSideMap[normalizedHandleId]) {\n return handleSideMap[normalizedHandleId];\n }\n\n // Known defaults\n if (normalizedHandleId === 'net-top' || normalizedHandleId === 'net-bottom') return 'front';\n if (normalizedHandleId === 'pwr-left-1' || normalizedHandleId === 'pwr-left-2' || normalizedHandleId === 'net-right-1' || normalizedHandleId === 'net-right-2') return 'rear';\n\n // Ports from arrays\n const frontBlocks = Array.isArray((data as { ports?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).ports)\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray((data as { rearPorts?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).rearPorts)\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).rearPorts!\n : [];\n\n // If the handleId matches a power label, treat as rear by default\n const looksLikePower = normalizedHandleId.startsWith('pwr') || normalizedHandleId.includes('power');\n if (looksLikePower) return 'rear';\n\n // Try to match against front port blocks\n for (const block of frontBlocks) {\n for (const port of block.ports || []) {\n const isPowerPort = !!port.type && String(port.type).includes('power');\n const expected = isPowerPort ? port.label : `${block.name}-${port.label}`;\n if (expected === normalizedHandleId) return 'front';\n }\n }\n // Try to match against rear port blocks\n for (const block of rearBlocks) {\n for (const port of block.ports || []) {\n const isPowerPort = !!port.type && String(port.type).includes('power');\n const expected = isPowerPort ? port.label : `${block.name}-${port.label}`;\n if (expected === normalizedHandleId) return 'rear';\n }\n }\n\n return undefined;\n}\n\nexport function createNetworkDiagramStore(initial: Partial<NetworkDiagramState> = {}, options: NetworkDiagramOptions = {}): NetworkDiagramStore {\n let state: NetworkDiagramState = {\n nodes: initial.nodes ?? [],\n edges: initial.edges ?? [],\n debug: initial.debug ?? false,\n };\n const listeners = new Set<(s: NetworkDiagramState) => void>();\n\n const getState = () => state;\n const setState = (partial: Partial<NetworkDiagramState>) => {\n state = { ...state, ...partial };\n listeners.forEach(l => l(state));\n };\n const subscribe = (listener: (s: NetworkDiagramState) => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n\n const selectEdgeZIndex = (edge: NetworkEdge): number => {\n const targetNode = state.nodes.find(n => n.id === edge.target);\n if (!targetNode || targetNode.type !== 'device') return 1000;\n const deviceView: ViewFace = (targetNode.data?.view as ViewFace) || 'front';\n const side = getHandleSide(edge.targetHandle || '', targetNode);\n if (side) return deviceView === side ? 1000 : 500;\n\n const targetHandle = (edge.targetHandle || '').toString();\n const targetHandleLc = targetHandle.toLowerCase();\n const isPowerHandle = targetHandleLc.startsWith('pwr') || targetHandleLc.startsWith('power');\n const isStandardNetworkHandle = targetHandleLc.startsWith('net-') || targetHandleLc.startsWith('port-') || targetHandleLc.startsWith('uplink-') || targetHandleLc.includes('fiber') || targetHandleLc.includes('ports');\n const isCustomPortName = /^[A-Z0-9]+-\\d+$/i.test(targetHandle) && !targetHandleLc.startsWith('pwr') && !targetHandleLc.startsWith('power');\n const isNetworkHandle = isStandardNetworkHandle || isCustomPortName;\n if (isPowerHandle) return deviceView === 'rear' ? 1000 : 500;\n if (isNetworkHandle) return deviceView === 'front' ? 1000 : 500;\n return 1000;\n };\n\n const validate = (params: ValidateConnectionParams): ValidationResult => {\n const fn = options.validateConnection || defaultValidateConnection;\n return fn(params, state);\n };\n\n const selectNodeById = (id: string) => state.nodes.find(n => n.id === id);\n const selectConnectedEdges = (nodeId: string) => state.edges.filter(e => e.source === nodeId || e.target === nodeId);\n\n return { getState, setState, subscribe, selectEdgeZIndex, validateConnection: validate, selectNodeById, selectConnectedEdges };\n}\n\n\n","import { useSyncExternalStore } from 'react';\nimport type { NetworkEdge, NetworkNode } from '../types';\nimport type { NetworkDiagramStore, NetworkDiagramState, ValidateConnectionParams, ValidationResult } from './store';\n\nexport function useNetworkDiagram(store: NetworkDiagramStore) {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState();\n const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n return state;\n}\n\nexport function useNodes(store: NetworkDiagramStore): NetworkNode[] {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState().nodes;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport function useEdges(store: NetworkDiagramStore): NetworkEdge[] {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState().edges;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport function useConnectionValidation(store: NetworkDiagramStore) {\n return (params: ValidateConnectionParams): ValidationResult => store.validateConnection(params);\n}\n\nexport function useSelectEdgeZIndex(store: NetworkDiagramStore) {\n return store.selectEdgeZIndex;\n}\n\n\n","import { NetworkNode } from '../types';\nimport { RACK_WIDTH_PX, U_HEIGHT_PX } from './constants';\n\n/**\n * Calculate the bounding box of a rack node\n * @param rack - The rack node\n * @returns Object with left, right, top, and bottom coordinates\n * @public\n */\nexport function getRackBounds(rack: NetworkNode): {\n left: number;\n right: number;\n top: number;\n bottom: number;\n} {\n const rackWidth = RACK_WIDTH_PX;\n const rackHeight = (rack.data.uHeight || 42) * U_HEIGHT_PX;\n const rackLeft = rack.position.x;\n const rackRight = rack.position.x + rackWidth;\n const rackTop = rack.position.y;\n const rackBottom = rack.position.y + rackHeight;\n\n return {\n left: rackLeft,\n right: rackRight,\n top: rackTop,\n bottom: rackBottom,\n };\n}\n\n/**\n * Check if a point is inside a rack's bounds\n * @param point - The point coordinates { x, y }\n * @param rack - The rack node\n * @returns True if the point is inside the rack\n * @public\n */\nexport function isPointInRack(point: { x: number; y: number }, rack: NetworkNode): boolean {\n const bounds = getRackBounds(rack);\n return (\n point.x >= bounds.left &&\n point.x <= bounds.right &&\n point.y >= bounds.top &&\n point.y <= bounds.bottom\n );\n}\n\n/**\n * Find the nearest rack to a point from a list of racks\n * Only considers racks that contain the point\n * @param point - The point coordinates { x, y }\n * @param racks - Array of rack nodes\n * @returns The nearest rack node, or null if no rack contains the point\n * @public\n */\nexport function findNearestRack(\n point: { x: number; y: number },\n racks: NetworkNode[]\n): NetworkNode | null {\n let nearestRack: NetworkNode | null = null;\n let minDistance = Infinity;\n\n for (const rack of racks) {\n if (!isPointInRack(point, rack)) {\n continue;\n }\n\n const distance = Math.sqrt(\n Math.pow(point.x - rack.position.x, 2) + Math.pow(point.y - rack.position.y, 2)\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestRack = rack;\n }\n }\n\n return nearestRack;\n}\n\n","import { Connection, Edge, addEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * Options for replacing an edge in the edges array\n */\nexport interface ReplaceEdgeOptions {\n /** Existing edges array */\n edges: Edge[];\n /** Connection parameters for the new edge */\n connection: Connection;\n /** Type of edge to create */\n edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';\n /** Function to calculate zIndex for the edge */\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n /** Whether to find edge by source or target */\n findBy: 'source' | 'target';\n /** Optional edge data to set on the new edge */\n data?: NetworkEdge['data'];\n}\n\n/**\n * Replace an existing edge with a new connection\n * This is used for PDU and switch connections that allow replacing existing edges\n * @param options - Options for edge replacement\n * @returns New edges array with the edge replaced, or null if no existing edge found\n * @public\n */\nexport function replaceEdge(\n options: ReplaceEdgeOptions\n): Edge[] | null {\n const { edges, connection, edgeType, selectEdgeZIndex, findBy, data } = options;\n\n // Determine which handle to search by\n const handleId = findBy === 'source' ? connection.sourceHandle : connection.targetHandle;\n const nodeId = findBy === 'source' ? connection.source : connection.target;\n\n if (!handleId || !nodeId) {\n return null;\n }\n\n // Find existing edge\n const existingEdge = edges.find(e => {\n if (findBy === 'source') {\n return e.source === nodeId && e.sourceHandle === handleId;\n } else {\n return e.target === nodeId && e.targetHandle === handleId;\n }\n });\n\n if (!existingEdge) {\n return null;\n }\n\n // Remove the existing edge\n const filtered = edges.filter(e => e.id !== existingEdge.id);\n\n // Create new edge using addEdge helper, then add type and zIndex\n const edgeFromAddEdge = addEdge(connection, filtered);\n \n // Find the newly added edge and update it with type, zIndex, and data\n const newEdge = edgeFromAddEdge[edgeFromAddEdge.length - 1];\n const zIndex = selectEdgeZIndex({ ...connection, id: newEdge.id, type: edgeType } as NetworkEdge);\n const edgeWithMetadata: Edge = {\n ...newEdge,\n type: edgeType,\n zIndex: zIndex,\n style: { ...newEdge.style, zIndex: zIndex },\n data: data !== undefined ? data : newEdge.data,\n };\n\n // Replace the last edge with the one that has metadata\n return [...edgeFromAddEdge.slice(0, -1), edgeWithMetadata];\n}\n\n","import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react';\nimport {\n ReactFlow,\n Background,\n Controls,\n MiniMap,\n useNodesState,\n useEdgesState,\n addEdge,\n Connection,\n Edge,\n Node,\n NodeTypes,\n EdgeTypes,\n useReactFlow,\n NodeChange,\n useOnSelectionChange,\n ReactFlowProvider,\n Panel,\n NodeProps,\n} from 'reactflow';\nimport { toPng } from 'html-to-image';\nimport { NetworkDiagramProps, NetworkNode, NetworkEdge } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from '../utils/constants';\nimport { RackNode } from './RackNode';\nimport { FiberNode } from './FiberNode';\nimport { FiberEdge } from './FiberEdge';\nimport { PowerEdge } from './PowerEdge';\nimport { SmoothStepFiberEdge } from './SmoothStepFiberEdge';\nimport { StepFiberEdge } from './StepFiberEdge';\nimport { DeviceNode } from './DeviceNode';\nimport { VerticalPDU } from './VerticalPDU';\nimport { SpliceNode } from './SpliceNode';\nimport { SpliceTrayNode } from './SpliceTrayNode';\nimport { TubeNode } from './TubeNode';\nimport { CableNode } from './CableNode';\nimport { snapToUPosition, calculateDevicePositionFromU } from '../utils/u-positioning';\nimport { createNetworkDiagramStore, getHandleSide } from '../core/store';\nimport { useEdges, useNodes, useSelectEdgeZIndex } from '../core/hooks';\nimport { isPointInRack, findNearestRack } from '../utils/rack-geometry';\nimport { replaceEdge } from '../utils/edge-connection';\nimport { getFiberColor, baseColorFor } from '../utils/fiber-colors';\nimport { snapToSplicePosition, calculateSplicePositionFromNumber } from '../utils/splice-positioning';\n\n// Create nodeTypes with onViewChange prop - memoized outside component\nconst createNodeTypes = (\n onViewChange?: (nodeId: string, view: 'front' | 'rear') => void,\n onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void,\n getDragOverRackId?: () => string | null\n): NodeTypes => ({\n rack: (props: NodeProps<NetworkNode['data']>) => <RackNode {...props} onViewChange={onViewChange} onRackFaceChange={onRackFaceChange} isDragOver={getDragOverRackId ? getDragOverRackId() === props.id : false} />,\n fiber: FiberNode,\n device: DeviceNode,\n 'vertical-pdu': VerticalPDU,\n splice: SpliceNode,\n 'splice-tray': SpliceTrayNode,\n tube: TubeNode,\n cable: CableNode,\n});\n\nconst edgeTypes: EdgeTypes = {\n fiber: FiberEdge,\n power: PowerEdge,\n smoothstep: SmoothStepFiberEdge,\n step: StepFiberEdge,\n};\n\nconst NetworkDiagramInner: React.FC<NetworkDiagramProps> = ({\n nodes,\n edges,\n initialNodes,\n initialEdges,\n onNodesChange: externalOnNodesChange,\n onEdgesChange: externalOnEdgesChange,\n store,\n debug,\n onNodeClick,\n onEdgeClick,\n onViewChange,\n onRackFaceChange,\n className,\n style,\n alignRacksToBottom,\n colorMode = 'dark',\n onInit,\n onFlowMethods,\n showDownloadButton = false,\n downloadButtonPosition = 'top-right',\n downloadButtonText = 'Download Image',\n downloadButtonStyle,\n allowReconnectExisting = false,\n useSmoothstepEdgesForTubes = false,\n}) => {\n // Decide controlled vs uncontrolled\n const isControlled = Array.isArray(nodes) && Array.isArray(edges);\n // Important: do not recreate store on nodes/edges changes to avoid perceived resets\n const localStore = React.useMemo(() => {\n if (store) return store;\n // Create store once; controlled updates will sync via effects below\n return createNetworkDiagramStore({\n nodes: isControlled ? (nodes || []) : (initialNodes || nodes || []),\n edges: isControlled ? (edges || []) : (initialEdges || edges || []),\n debug,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store, isControlled, debug]);\n\n // Local React Flow states mirror store state for rendering\n const storeNodes = useNodes(localStore);\n const storeEdges = useEdges(localStore);\n const [reactFlowNodes, setNodes, onNodesChange] = useNodesState(storeNodes);\n const [reactFlowEdges, setEdges, onEdgesChange] = useEdgesState(storeEdges);\n const selectEdgeZIndex = useSelectEdgeZIndex(localStore);\n const reactFlowWrapper = useRef<HTMLDivElement>(null);\n \n // Get React Flow methods for save/restore\n const { toObject, setViewport, setNodes: setReactFlowNodes, setEdges: setReactFlowEdges, getNodes } = useReactFlow();\n \n // Type for html-to-image options\n interface ToImageOptions {\n width?: number;\n height?: number;\n backgroundColor?: string;\n padding?: number;\n pixelRatio?: number;\n quality?: number;\n filter?: (domNode: HTMLElement) => boolean;\n }\n \n // Expose React Flow methods to parent component\n useEffect(() => {\n if (onFlowMethods) {\n onFlowMethods({\n toObject,\n setViewport,\n setNodes: (nodes: Node[]) => {\n setReactFlowNodes(nodes);\n localStore.setState({ nodes: nodes as NetworkNode[] });\n },\n setEdges: (edges: Edge[]) => {\n setReactFlowEdges(edges);\n localStore.setState({ edges: edges as NetworkEdge[] });\n },\n toImage: (options?: ToImageOptions) => {\n if (!reactFlowWrapper.current) return Promise.reject(new Error('ReactFlow wrapper not available'));\n return toPng(reactFlowWrapper.current, options);\n }\n });\n }\n }, [onFlowMethods, toObject, setViewport, setReactFlowNodes, setReactFlowEdges, localStore]);\n\n // Download functionality\n const onDownload = useCallback(() => {\n if (!reactFlowWrapper.current) {\n if (debug) {\n console.error('ReactFlow wrapper ref is not available');\n }\n return;\n }\n \n toPng(reactFlowWrapper.current, {\n filter: (node) =>\n !(\n node?.classList?.contains('react-flow__minimap') ||\n node?.classList?.contains('react-flow__controls') ||\n node?.classList?.contains('react-flow__attribution') ||\n node?.classList?.contains('download-button') ||\n node?.tagName === 'BUTTON'\n ),\n backgroundColor: colorMode === 'light' ? '#ffffff' : '#1a1a1a',\n pixelRatio: 2,\n }).then((dataUrl: string) => {\n const link = document.createElement('a');\n link.download = `network-diagram-${new Date().toISOString().split('T')[0]}.png`;\n link.href = dataUrl;\n link.click();\n }).catch((error: unknown) => {\n if (debug) {\n console.error('Error downloading image:', error);\n }\n });\n }, [colorMode, debug]);\n \n // Track which rack is being dragged over for visual feedback\n const [dragOverRackId, setDragOverRackId] = useState<string | null>(null);\n const dragOverRackIdRef = useRef<string | null>(null);\n \n // Store callbacks in refs to keep nodeTypes stable even if callbacks change\n const onViewChangeRef = useRef(onViewChange);\n const onRackFaceChangeRef = useRef(onRackFaceChange);\n \n // Update refs when callbacks change\n useEffect(() => {\n onViewChangeRef.current = onViewChange;\n }, [onViewChange]);\n \n useEffect(() => {\n onRackFaceChangeRef.current = onRackFaceChange;\n }, [onRackFaceChange]);\n \n // Update ref when state changes\n useEffect(() => {\n dragOverRackIdRef.current = dragOverRackId;\n }, [dragOverRackId]);\n \n // Create stable function reference for getting dragOverRackId\n const getDragOverRackId = useRef(() => dragOverRackIdRef.current);\n \n // Memoize nodeTypes to avoid recreating object every render (prevents node remounts)\n // Use refs for callbacks to keep nodeTypes stable even if callbacks change\n const memoizedNodeTypes = useMemo(\n () => createNodeTypes(\n (nodeId, view) => onViewChangeRef.current?.(nodeId, view),\n (rackId, face) => onRackFaceChangeRef.current?.(rackId, face),\n getDragOverRackId.current\n ),\n [] // Empty deps - nodeTypes object is now truly stable\n );\n \n // Memoize edgeTypes to prevent recreation warnings\n const memoizedEdgeTypes = useMemo(() => edgeTypes, []);\n\n\n // Maintain the latest nodes in a ref for always-current lookups in callbacks\n const latestNodesRef = useRef<Node[]>(reactFlowNodes);\n useEffect(() => { latestNodesRef.current = reactFlowNodes; }, [reactFlowNodes]);\n\n // Maintain the latest edges in a ref for always-current lookups in callbacks\n const latestEdgesRef = useRef<Edge[]>(reactFlowEdges);\n useEffect(() => { latestEdgesRef.current = reactFlowEdges; }, [reactFlowEdges]);\n\n // Sync store -> RF state updates\n useEffect(() => { setNodes(storeNodes); }, [storeNodes, setNodes]);\n useEffect(() => { setEdges(storeEdges); }, [storeEdges, setEdges]);\n // Sync controlled props -> store (if controlled)\n useEffect(() => {\n if (isControlled) {\n localStore.setState({ nodes: nodes || [] });\n }\n }, [isControlled, nodes, localStore]);\n useEffect(() => {\n if (isControlled) {\n localStore.setState({ edges: edges || [] });\n }\n }, [isControlled, edges, localStore]);\n\n // Optionally align rack bottoms to a common baseline\n useEffect(() => {\n if (!alignRacksToBottom) return;\n if (!reactFlowNodes || reactFlowNodes.length === 0) return;\n\n const racks = reactFlowNodes.filter(n => n.type === 'rack');\n if (racks.length === 0) return;\n\n // Compute each rack's bottom (y + header + uHeight * U_HEIGHT_PX)\n const rackBottoms = racks.map(r => {\n const rackData = r.data as NetworkNode['data'];\n const uHeight = rackData?.uHeight || 42;\n const heightPx = RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX;\n return (r.position?.y || 0) + heightPx;\n });\n \n // Find the range of bottom positions\n const minBottom = Math.min(...rackBottoms);\n const maxBottom = Math.max(...rackBottoms);\n const range = maxBottom - minBottom;\n \n // Only align if there's a significant difference (more than 20px)\n // This prevents constant micro-adjustments during dragging\n if (range < 20) return;\n \n // Use the highest bottom as the baseline (floor level)\n const baselineBottom = maxBottom;\n\n // Align all racks to the baseline - move them up or down as needed\n const nextNodes = reactFlowNodes.map(n => {\n if (n.type !== 'rack') return n;\n const nodeData = n.data as NetworkNode['data'];\n const uHeight = nodeData?.uHeight || 42;\n const heightPx = RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX;\n const currentBottom = (n.position?.y || 0) + heightPx;\n const delta = baselineBottom - currentBottom;\n if (Math.abs(delta) < 5) return n; // Don't make tiny adjustments\n return {\n ...n,\n position: {\n x: n.position?.x || 0,\n y: (n.position?.y || 0) + delta,\n },\n } as Node;\n });\n\n const changed = nextNodes.some((n, i) => n.position !== reactFlowNodes[i].position);\n if (changed) setNodes(nextNodes);\n }, [alignRacksToBottom, reactFlowNodes, setNodes]);\n\n // Helper: always get current version of a node (beyond closure scope issue)\n const getNodeById = useCallback((id: string) => {\n return latestNodesRef.current.find(n => n.id === id);\n }, []);\n\n // Helper: derive fiber color from source node handle\n // For tube nodes: handle ID is \"fiber-<n>\" where n is 1-24, use TIA color\n // For cable nodes: handle ID is \"tube-<n>\" representing buffer tubes (1-24), use tube color\n // For tube-to-cable connections: hidden handles share the same \"tube-<n>\" pattern\n // For other nodes: check node data color\n const deriveFiberColorFromSource = useCallback((sourceNodeId: string, sourceHandle: string | null | undefined): { color: string; striped?: boolean } | undefined => {\n if (!sourceNodeId || !sourceHandle) return undefined;\n const sourceNode = getNodeById(sourceNodeId);\n if (!sourceNode) return undefined;\n \n // For tube nodes, extract fiber number from handle ID (format: \"fiber-<n>\")\n if (sourceNode.type === 'tube' && sourceHandle.startsWith('fiber-')) {\n const fiberNumStr = sourceHandle.replace('fiber-', '');\n const fiberNum = parseInt(fiberNumStr, 10);\n if (fiberNum >= 1 && fiberNum <= 24) {\n const color = getFiberColor(fiberNum);\n const striped = fiberNum > 12;\n return { color, striped };\n }\n }\n\n if ((sourceNode.type === 'cable' || sourceNode.type === 'tube') && sourceHandle.startsWith('tube-')) {\n const tubeNumStr = sourceHandle.replace('tube-', '');\n const tubeNum = parseInt(tubeNumStr, 10);\n if (tubeNum >= 1 && tubeNum <= 24) {\n const color = baseColorFor(tubeNum);\n const striped = tubeNum > 12;\n return { color, striped };\n }\n }\n \n // For other node types, check node data color\n const nodeData = sourceNode.data as NetworkNode['data'];\n if (nodeData.color) {\n return { color: nodeData.color };\n }\n \n return undefined;\n }, [getNodeById]);\n\n // Update edges zIndex when nodes change\n useEffect(() => {\n setEdges((eds) =>\n eds.map(edge => {\n const newZIndex = selectEdgeZIndex(edge as NetworkEdge);\n return {\n ...edge,\n zIndex: newZIndex,\n style: { ...edge.style, zIndex: newZIndex }\n };\n })\n );\n }, [reactFlowNodes, setEdges, selectEdgeZIndex]);\n\n useEffect(() => {\n const updatedNodes = reactFlowNodes.map(node => {\n // Handle splice positioning\n if (\n node.type === 'splice' &&\n node.parentId &&\n node.data.holderPosition &&\n (!node.position || (node.position.x === 0 && node.position.y === 0))\n ) {\n const parentTray = getNodeById(node.parentId);\n if (parentTray && parentTray.type === 'splice-tray') {\n const calculatedPosition = calculateSplicePositionFromNumber(parentTray as NetworkNode, node.data.holderPosition);\n return {\n ...node,\n position: calculatedPosition,\n };\n }\n }\n // Handle device positioning\n if (\n node.type === 'device' &&\n node.parentId &&\n node.data.uPosition &&\n (!node.position || (node.position.x === 0 && node.position.y === 0))\n ) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const calculatedPosition = calculateDevicePositionFromU(parentRack as NetworkNode, node.data.uPosition);\n return {\n ...node,\n position: calculatedPosition,\n };\n }\n }\n return node;\n });\n\n const hasChanges = updatedNodes.some((node, index) =>\n node.position !== reactFlowNodes[index].position\n );\n if (hasChanges) {\n setNodes(updatedNodes);\n }\n }, [reactFlowNodes, setNodes, getNodeById]);\n\n const handleNodesChange = useCallback((changes: NodeChange[]) => {\n const updatedChanges = changes.map((change) => {\n if (change.type === 'position' && change.position) {\n const node = getNodeById(change.id);\n\n // Handle splice positioning within tray\n if (node && node.type === 'splice' && node.parentId) {\n const parentTray = getNodeById(node.parentId);\n if (parentTray && parentTray.type === 'splice-tray') {\n const snappedResult = snapToSplicePosition(\n node as NetworkNode,\n parentTray as NetworkNode,\n change.position,\n latestNodesRef.current as NetworkNode[]\n );\n\n if (snappedResult.holderPosition !== undefined) {\n const updatedNode = {\n ...node,\n data: {\n ...node.data,\n holderPosition: snappedResult.holderPosition,\n },\n };\n\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n // Handle device positioning within rack\n if (node && node.type === 'device' && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const snappedResult = snapToUPosition(\n node as NetworkNode,\n parentRack as NetworkNode,\n change.position,\n latestNodesRef.current as NetworkNode[]\n );\n\n if (snappedResult.uPosition !== undefined) {\n const updatedNode = {\n ...node,\n data: {\n ...node.data,\n uPosition: snappedResult.uPosition,\n },\n };\n\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n\n if (node && node.type === 'device' && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const rackNode = parentRack as NetworkNode;\n\n if (!isPointInRack(change.position, rackNode)) {\n const absoluteX = change.position.x + rackNode.position.x;\n const absoluteY = change.position.y + rackNode.position.y;\n const updatedNode = {\n ...node,\n parentId: undefined,\n extent: undefined,\n data: {\n ...node.data,\n uPosition: undefined,\n },\n };\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n return { ...change, position: { x: absoluteX, y: absoluteY } };\n }\n }\n }\n }\n return change;\n });\n\n onNodesChange(updatedChanges);\n }, [onNodesChange, setNodes, getNodeById]);\n\n // Handle drag start to track which node is being dragged\n const handleNodeDragStart = useCallback((_event: React.MouseEvent, _node: Node) => {\n // Reset drag over state when starting a new drag\n setDragOverRackId(null);\n }, []);\n\n // Handle drag over to detect when device is over a rack\n const handleNodeDrag = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n if (node.type === 'device' && !node.parentId) {\n // Find the nearest rack\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const nearestRack = findNearestRack(node.position, racks);\n\n // Update drag over state\n setDragOverRackId(nearestRack?.id ?? null);\n } else {\n setDragOverRackId(null);\n }\n }, []);\n\n // Handle drag end to group ungrouped nodes into racks\n const handleNodeDragStop = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n if (node.type === 'device' && !node.parentId) {\n // Find the nearest rack\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const nearestRack = findNearestRack(node.position, racks);\n\n if (nearestRack) {\n // Calculate relative position\n const relativeX = node.position.x - nearestRack.position.x;\n const relativeY = node.position.y - nearestRack.position.y;\n \n // Update the node with parent relationship and new position\n const updatedNode = {\n ...node,\n parentId: nearestRack.id,\n extent: 'parent' as const,\n position: { x: relativeX, y: relativeY },\n data: {\n ...node.data,\n uPosition: 1,\n },\n };\n \n const updatedNodes = latestNodesRef.current.map(n => n.id === node.id ? updatedNode : n);\n setNodes(updatedNodes);\n \n // Update store in uncontrolled mode\n if (!isControlled) {\n localStore.setState({ nodes: updatedNodes as NetworkNode[] });\n }\n }\n }\n \n // Clear drag over state when drag ends\n setDragOverRackId(null);\n }, [setNodes, isControlled, localStore]);\n\n // Connection validation for React Flow - allows connections before onConnect validation\n const isValidConnection = useCallback((connection: Connection): boolean => {\n if (!connection.source || !connection.target || !connection.sourceHandle || !connection.targetHandle) {\n return true;\n }\n\n const sourceNode = getNodeById(connection.source);\n const targetNode = getNodeById(connection.target);\n\n // Prevent connections between fibres in tubes (both source and target are tube nodes with fiber handles)\n if (\n sourceNode?.type === 'tube' &&\n targetNode?.type === 'tube' &&\n connection.sourceHandle.startsWith('fiber-') &&\n connection.targetHandle.startsWith('fiber-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect fibres within tubes', connection);\n }\n return false;\n }\n\n // Prevent individual fibre connections to cable tube handles\n // Tube fiber handles (fiber-*) should not connect to cable/tube tube handles (tube-*)\n if (\n sourceNode?.type === 'tube' &&\n connection.sourceHandle.startsWith('fiber-') &&\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n connection.targetHandle.startsWith('tube-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect individual fibre to cable/tube tube handle', connection);\n }\n return false;\n }\n\n // Prevent cable/tube tube handles from connecting to individual fibre handles\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n connection.sourceHandle.startsWith('tube-') &&\n targetNode?.type === 'tube' &&\n connection.targetHandle.startsWith('fiber-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect cable/tube tube handle to individual fibre', connection);\n }\n return false;\n }\n\n // Check if splice target handle is already connected - only allow one edge per handle\n if (targetNode?.type === 'splice' && (connection.targetHandle === 'left' || connection.targetHandle === 'right')) {\n // Check both target and source (right handle can be either)\n const existingEdge = latestEdgesRef.current.find(\n (e) => (e.target === connection.target && e.targetHandle === connection.targetHandle) ||\n (e.source === connection.target && e.sourceHandle === connection.targetHandle)\n );\n if (existingEdge) {\n if (debug) {\n console.log('Splice handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection to splice handle', connection);\n }\n return true;\n }\n\n // Check if tube fiber source handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube fiber handles (fiber-*) can ONLY connect to splices\n if (sourceNode?.type === 'tube' && connection.sourceHandle.startsWith('fiber-')) {\n // Validate that fiber handles can only connect to splices\n if (targetNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Tube fiber handles can only connect to splices', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube fiber handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube fiber handle to splice', connection);\n }\n return true;\n }\n\n // Check if cable/tube tube-level source handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube handles (tube-*) can ONLY connect to other tube handles (tube-*)\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n connection.sourceHandle.startsWith('tube-')\n ) {\n // Validate that tube handles can only connect to other tube handles\n if (!connection.targetHandle.startsWith('tube-')) {\n if (debug) {\n console.log('Connection rejected: Tube handles can only connect to other tube handles', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube-level handle already connected, will replace', connection);\n }\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube-level handle to tube handle', connection);\n }\n return true;\n }\n\n // Check if splice source handle is already connected - only allow one edge per handle\n if (sourceNode?.type === 'splice' && connection.sourceHandle === 'right') {\n // Check both source and target (right handle can be either)\n const existingEdge = latestEdgesRef.current.find(\n (e) => (e.source === connection.source && e.sourceHandle === connection.sourceHandle) ||\n (e.target === connection.source && e.targetHandle === connection.sourceHandle)\n );\n if (existingEdge) {\n if (debug) {\n console.log('Splice source handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n return true;\n }\n\n // Check if tube fiber target handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube fiber handles (fiber-*) can ONLY connect to splices\n if (targetNode?.type === 'tube' && connection.targetHandle.startsWith('fiber-')) {\n // Validate that fiber handles can only connect from splices\n if (sourceNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Tube fiber handles can only connect from splices', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube fiber target handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from splice to tube fiber handle', connection);\n }\n return true;\n }\n\n // Check if cable/tube tube-level target handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube handles (tube-*) can ONLY connect to other tube handles (tube-*)\n if (\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n connection.targetHandle.startsWith('tube-')\n ) {\n // Validate that tube handles can only connect from other tube handles\n if (!connection.sourceHandle.startsWith('tube-')) {\n if (debug) {\n console.log('Connection rejected: Tube handles can only connect from other tube handles', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube-level target handle already connected, will replace', connection);\n }\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube handle to tube-level handle', connection);\n }\n return true;\n }\n\n // For all other connections, use the store validation (which also recognizes tube/splice as network)\n const validation = localStore.validateConnection({\n source: connection.source ?? null,\n target: connection.target ?? null,\n sourceHandle: connection.sourceHandle ?? null,\n targetHandle: connection.targetHandle ?? null,\n });\n\n // If validation fails but allowReconnectExisting is enabled, check if there's an existing edge\n // on either the source or target handle that we can replace\n if (!validation.valid && allowReconnectExisting) {\n // Check if source handle has an existing edge\n if (connection.source && connection.sourceHandle) {\n const sourceEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (sourceEdge) {\n if (debug) {\n console.log('Source handle has existing edge, will replace', connection);\n }\n return true;\n }\n }\n // Check if target handle has an existing edge\n if (connection.target && connection.targetHandle) {\n const targetEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (targetEdge) {\n if (debug) {\n console.log('Target handle has existing edge, will replace', connection);\n }\n return true;\n }\n }\n }\n\n if (debug && !validation.valid) {\n console.log('Connection rejected by store validation:', validation.reason, connection);\n }\n\n return validation.valid;\n }, [getNodeById, localStore, debug, allowReconnectExisting]);\n\n const onConnect = useCallback(\n (params: Connection) => {\n const sourceNode = getNodeById(params.source!);\n const targetNode = getNodeById(params.target!);\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const isSwitchSource = sourceNode?.type === 'device' && sourceNodeData?.deviceType === 'switch';\n const looksLikePowerTarget = !!params.targetHandle && (params.targetHandle.startsWith('pwr') || params.targetHandle.startsWith('power'));\n const looksLikeNetworkTarget = !!params.targetHandle && (\n params.targetHandle.startsWith('net-') || \n params.targetHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(params.targetHandle) // Custom port names like \"QSFP28-1\"\n );\n\n // Determine edge type: step for tube > cable, power for PDU connections, fiber otherwise\n const isTubeToCable = sourceNode?.type === 'tube' && targetNode?.type === 'cable';\n const isCableToTube = sourceNode?.type === 'cable' && targetNode?.type === 'tube';\n const isTubeConnection = isTubeToCable || isCableToTube;\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';\n if (isPduSource && looksLikePowerTarget) {\n edgeType = 'power';\n } else if (isTubeConnection) {\n // Use smoothstep edges if useSmoothstepEdgesForTubes is true, otherwise use fiber (default)\n edgeType = useSmoothstepEdgesForTubes ? 'smoothstep' : 'fiber';\n } else {\n edgeType = 'fiber';\n }\n \n // Derive fiber color from source node handle (for fiber/smoothstep edges)\n let edgeData: { color?: string; striped?: boolean } | undefined;\n if ((edgeType === 'fiber' || edgeType === 'smoothstep') && !isPduSource) {\n const colorInfo = deriveFiberColorFromSource(params.source!, params.sourceHandle);\n if (colorInfo) {\n edgeData = { color: colorInfo.color, striped: colorInfo.striped };\n }\n }\n\n // Replace existing edge on splice target handle (left or right) - only one edge per handle\n // Right handle can be either source or target, so check both\n if (targetNode?.type === 'splice' && (params.targetHandle === 'left' || params.targetHandle === 'right') && params.target && params.targetHandle) {\n // Try replacing as target first\n let newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n // If right handle and not found as target, try as source (right handle can be either)\n if (params.targetHandle === 'right') {\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n }\n\n // Replace existing edge on splice source handle (right) - only one edge per handle\n // Right handle can be either source or target, so check both\n if (sourceNode?.type === 'splice' && params.sourceHandle === 'right' && params.source && params.sourceHandle) {\n // Try replacing as source first\n let newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n // If not found as source, try as target (right handle can be either)\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on tube fiber source handle - only one edge per handle\n if (sourceNode?.type === 'tube' && params.sourceHandle?.startsWith('fiber-') && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on tube fiber target handle - only one edge per handle\n if (targetNode?.type === 'tube' && params.targetHandle?.startsWith('fiber-') && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n params.sourceHandle?.startsWith('tube-') &&\n params.source &&\n params.sourceHandle\n ) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n if (\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n params.targetHandle?.startsWith('tube-') &&\n params.target &&\n params.targetHandle\n ) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Try to replace existing edge on target for PDU power connections\n if (isPduSource && looksLikePowerTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Allow replacing existing network edge on target when connecting from switch (like power PDU behavior)\n if (isSwitchSource && looksLikeNetworkTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n const validation = localStore.validateConnection({\n source: params.source ?? null,\n target: params.target ?? null,\n sourceHandle: params.sourceHandle ?? null,\n targetHandle: params.targetHandle ?? null,\n });\n if (!validation.valid) {\n // If allowReconnectExisting is enabled, try to replace existing edge from either end\n if (allowReconnectExisting) {\n // Try replacing from source handle\n if (params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n // Try replacing from target handle\n if (params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n }\n \n // Try to replace existing edge on source for PDU connections (legacy behavior)\n if (isPduSource && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: looksLikePowerTarget ? 'power' : 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n // Allow replacing existing network edge on source when connecting from switch (like power PDU behavior)\n if (isSwitchSource && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n if (debug) {\n console.warn(`Connection rejected: ${validation.reason}`);\n }\n return;\n }\n\n const edgeToAdd = {\n ...params,\n type: edgeType,\n zIndex: selectEdgeZIndex({ ...params, id: 'temp-id' } as NetworkEdge),\n data: edgeData,\n } as Connection;\n\n setEdges((eds) => {\n const newEdges = addEdge(edgeToAdd, eds);\n // Find the newly added edge and animate it\n const newEdge = newEdges[newEdges.length - 1];\n if (newEdge) {\n setAnimatingEdges((prev) => new Set(prev).add(newEdge.id));\n // Remove animation class after animation completes\n setTimeout(() => {\n setAnimatingEdges((prev) => {\n const next = new Set(prev);\n next.delete(newEdge.id);\n return next;\n });\n }, 1000); // Animation duration matches CSS\n }\n return newEdges;\n });\n },\n [setEdges, localStore, selectEdgeZIndex, getNodeById, debug, deriveFiberColorFromSource, allowReconnectExisting, useSmoothstepEdgesForTubes]\n );\n\n // Handle edge updates (when user drags an edge endpoint to reconnect)\n const onEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (!newConnection.source || !newConnection.target || !newConnection.sourceHandle || !newConnection.targetHandle) {\n return;\n }\n\n // Prevent reconnection that would disconnect tube handles\n const oldSourceHandle = oldEdge.sourceHandle || '';\n const oldTargetHandle = oldEdge.targetHandle || '';\n const newSourceHandle = newConnection.sourceHandle || '';\n const newTargetHandle = newConnection.targetHandle || '';\n \n // If old edge has a tube handle on source, new connection must keep the same tube handle\n if (oldSourceHandle.startsWith('tube-') && newSourceHandle !== oldSourceHandle) {\n if (debug) {\n console.log('Edge update blocked: Cannot disconnect tube handle', { oldEdge, newConnection });\n }\n return; // Prevent the update\n }\n \n // If old edge has a tube handle on target, new connection must keep the same tube handle\n if (oldTargetHandle.startsWith('tube-') && newTargetHandle !== oldTargetHandle) {\n if (debug) {\n console.log('Edge update blocked: Cannot disconnect tube handle', { oldEdge, newConnection });\n }\n return; // Prevent the update\n }\n\n const sourceNode = getNodeById(newConnection.source);\n const targetNode = getNodeById(newConnection.target);\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const looksLikePowerTarget = !!newConnection.targetHandle && (newConnection.targetHandle.startsWith('pwr') || newConnection.targetHandle.startsWith('power'));\n const isTubeToCable = sourceNode?.type === 'tube' && targetNode?.type === 'cable';\n const isCableToTube = sourceNode?.type === 'cable' && targetNode?.type === 'tube';\n const isTubeConnection = isTubeToCable || isCableToTube;\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';\n if (isPduSource && looksLikePowerTarget) {\n edgeType = 'power';\n } else if (isTubeConnection) {\n edgeType = useSmoothstepEdgesForTubes ? 'smoothstep' : 'fiber';\n } else {\n edgeType = 'fiber';\n }\n\n // Derive fiber color from new source node handle\n let edgeData: { color?: string; striped?: boolean } | undefined;\n if ((edgeType === 'fiber' || edgeType === 'smoothstep') && !isPduSource) {\n const colorInfo = deriveFiberColorFromSource(newConnection.source, newConnection.sourceHandle);\n if (colorInfo) {\n edgeData = { color: colorInfo.color, striped: colorInfo.striped };\n }\n }\n\n // Update the edge with new connection and recalculated data\n setEdges((eds) => {\n const updated = eds.map((e) => {\n if (e.id === oldEdge.id) {\n return {\n ...e,\n source: newConnection.source!,\n target: newConnection.target!,\n sourceHandle: newConnection.sourceHandle,\n targetHandle: newConnection.targetHandle,\n type: edgeType,\n data: edgeData !== undefined ? { ...e.data, ...edgeData } : e.data,\n zIndex: selectEdgeZIndex({ ...newConnection, id: e.id, type: edgeType } as NetworkEdge),\n style: { ...e.style, zIndex: selectEdgeZIndex({ ...newConnection, id: e.id, type: edgeType } as NetworkEdge) },\n };\n }\n return e;\n });\n return updated;\n });\n },\n [setEdges, getNodeById, deriveFiberColorFromSource, selectEdgeZIndex, useSmoothstepEdgesForTubes]\n );\n\n const handleNodeClick = useCallback(\n (event: React.MouseEvent, node: Node) => {\n const isCommandClick = event.metaKey || event.ctrlKey;\n\n // If a tube is clicked and it has a parent cable, select the parent instead\n if (node.type === 'tube' && node.parentId && !isCommandClick) {\n const allNodes = getNodes();\n const parentNode = allNodes.find(n => n.id === node.parentId && n.type === 'cable');\n if (parentNode) {\n // Select the parent cable in React Flow\n setNodes((nds) => nds.map((n) => ({ ...n, selected: n.id === parentNode.id })));\n if (onNodeClick) {\n onNodeClick(parentNode as NetworkNode);\n }\n return;\n }\n }\n\n if (isCommandClick && node.type === 'device') {\n const data = node.data || {};\n const currentView: 'front' | 'rear' = data.view || (Array.isArray(data.rearPorts) && data.rearPorts.length > 0 ? 'rear' : 'front');\n const nextView: 'front' | 'rear' = currentView === 'front' ? 'rear' : 'front';\n\n if (debug) {\n console.log(`Command+click: Toggling device ${node.id} from ${currentView} to ${nextView}`);\n }\n\n // Use external onViewChange instead of internal state management\n if (onViewChange) {\n onViewChange(node.id, nextView);\n }\n\n onNodeClick && onNodeClick(node as NetworkNode);\n } else {\n // Allow regular clicks on all nodes (including devices) to trigger selection\n // React Flow will handle the selection, and useOnSelectionChange will call onNodeClick\n onNodeClick && onNodeClick(node as NetworkNode);\n }\n },\n [onViewChange, onNodeClick, debug, getNodes, setNodes]\n );\n\n // Double-click no longer removes edges to avoid accidental disconnects during interactions\n const handleNodeDoubleClick = useCallback(() => {}, []);\n\n const handleEdgeClick = useCallback(\n (event: React.MouseEvent, edge: Edge) => {\n if (onEdgeClick) {\n onEdgeClick(edge as NetworkEdge);\n }\n },\n [onEdgeClick]\n );\n\n // Track selection to show a toggle UI\n const [selectedNode, setSelectedNode] = useState<Node | null>(null);\n const [animatingEdges, setAnimatingEdges] = useState<Set<string>>(new Set());\n \n useOnSelectionChange({\n onChange: ({ nodes }) => {\n if (nodes && nodes.length === 1) {\n const node = nodes[0];\n // If a tube is selected and it has a parent, select the parent cable instead\n if (node.type === 'tube' && node.parentId) {\n const allNodes = getNodes();\n const parentNode = allNodes.find(n => n.id === node.parentId && n.type === 'cable');\n if (parentNode) {\n setSelectedNode(parentNode);\n // Select the parent cable in React Flow\n setNodes((nds) => nds.map((n) => ({ ...n, selected: n.id === parentNode.id })));\n if (onNodeClick) {\n onNodeClick(parentNode as NetworkNode);\n }\n return;\n }\n }\n setSelectedNode(node);\n // Also call onNodeClick when a node is selected via React Flow selection\n // This ensures device nodes can be selected even if regular clicks don't trigger onNodeClick\n if (onNodeClick) {\n onNodeClick(node as NetworkNode);\n }\n } else {\n setSelectedNode(null);\n // Clear selection in parent when no nodes are selected\n if (onNodeClick) {\n onNodeClick(null);\n }\n }\n },\n });\n\n // Handle connection start - track when user starts connecting\n const handleConnectStart = useCallback(\n (_event: React.MouseEvent | React.TouchEvent, { nodeId, handleType }: { nodeId: string | null; handleType: string | null }) => {\n if (debug) {\n console.log('Connection started from', { nodeId, handleType });\n }\n },\n [debug]\n );\n\n // Handle connection end - animate the newly created edge\n const handleConnectEnd = useCallback(\n (event: MouseEvent | TouchEvent) => {\n // The edge will be added via onConnect, so we'll track it there\n if (debug) {\n console.log('Connection ended', event);\n }\n },\n [debug]\n );\n\n const toggleSelectedFace = useCallback(() => {\n if (!selectedNode) return;\n const node = getNodeById(selectedNode.id);\n if (!node) return;\n\n if (node.type === 'rack') {\n const nodeData = (node.data as NetworkNode['data']) || {};\n const currentFace: 'front' | 'rear' = (nodeData.face as 'front' | 'rear') || 'front';\n const next: 'front' | 'rear' = currentFace === 'front' ? 'rear' : 'front';\n if (onRackFaceChange) {\n onRackFaceChange(node.id, next);\n // Also propagate to child devices via onViewChange if provided\n if (onViewChange) {\n const childNodes = getNodes().filter(n => n.parentId === node.id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n }\n } else {\n // Fallback: update rack face and propagate to child devices' view\n setNodes((nodes) => nodes.map(n => {\n if (n.id === node.id) {\n return { ...n, data: { ...n.data, face: next } } as Node;\n }\n if (n.parentId === node.id) {\n return { ...n, data: { ...n.data, view: next } } as Node;\n }\n return n;\n }));\n }\n return;\n }\n\n if (node.type === 'device') {\n const nodeData = (node.data as NetworkNode['data']) || {};\n const hasRear = Array.isArray(nodeData.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData.ports) && nodeData.ports.length > 0;\n const currentView: 'front' | 'rear' = (nodeData.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n const next: 'front' | 'rear' = currentView === 'front' ? 'rear' : 'front';\n if (onViewChange) {\n onViewChange(node.id, next);\n } else {\n setNodes((nodes) => nodes.map(n => n.id === node.id ? ({ ...n, data: { ...n.data, view: next } } as Node) : n));\n }\n }\n }, [selectedNode, getNodeById, onRackFaceChange, onViewChange, setNodes]);\n\n // Add animation class and apply rear/front visibility rules\n const edgesWithAnimation = useMemo(() => {\n return reactFlowEdges.map(edge => {\n const e = edge as unknown as NetworkEdge;\n // Resolve endpoints\n const sourceNode = getNodeById(String(e.source)) as unknown as Node | undefined;\n const targetNode = getNodeById(String(e.target)) as unknown as Node | undefined;\n // Determine handle sides\n const sourceSide = getHandleSide((e.sourceHandle || '') as string, sourceNode as unknown as NetworkNode);\n const targetSide = getHandleSide((e.targetHandle || '') as string, targetNode as unknown as NetworkNode);\n // Determine endpoint views\n const sourceView = (sourceNode && (sourceNode as any).data?.view) as 'front' | 'rear' | undefined;\n const targetView = (targetNode && (targetNode as any).data?.view) as 'front' | 'rear' | undefined;\n const sourceIsRear = sourceNode?.type === 'device' && sourceView === 'rear';\n const targetIsRear = targetNode?.type === 'device' && targetView === 'rear';\n // Hide when both endpoints that are in rear view do not use rear handles\n const hideForSource = sourceIsRear && sourceSide !== 'rear';\n const hideForTarget = targetIsRear && targetSide !== 'rear';\n const shouldHide = hideForSource && hideForTarget;\n // Compose styles\n const nextStyle: React.CSSProperties | undefined = shouldHide\n ? { ...edge.style, opacity: 0, pointerEvents: 'none' as const, zIndex: 0 }\n : edge.style;\n return {\n ...edge,\n style: nextStyle,\n className: animatingEdges.has(edge.id) ? 'edge-connecting' : edge.className,\n };\n });\n }, [reactFlowEdges, animatingEdges, getNodeById]);\n\n return (\n <div ref={reactFlowWrapper} className={`${className || ''} ${colorMode === 'light' ? 'react-flow-light' : 'react-flow-dark'}`} style={{ width: '100%', height: '100%', ...style }}>\n <ReactFlow\n nodes={reactFlowNodes}\n edges={edgesWithAnimation}\n onNodesChange={(changes) => {\n handleNodesChange(changes);\n if (!isControlled) {\n localStore.setState({ nodes: latestNodesRef.current as NetworkNode[] });\n } else {\n externalOnNodesChange && externalOnNodesChange(latestNodesRef.current as NetworkNode[]);\n }\n }}\n onEdgesChange={(changes) => {\n // Filter out deletions of edges connected to tube handles (tube-* handles)\n const filteredChanges = changes.filter((change) => {\n if (change.type === 'remove') {\n // Find the edge being removed\n const edgeToRemove = latestEdgesRef.current.find((e) => e.id === change.id);\n if (edgeToRemove) {\n // Check if either handle is a tube handle (tube-*)\n const sourceHandle = edgeToRemove.sourceHandle || '';\n const targetHandle = edgeToRemove.targetHandle || '';\n const isTubeHandle = sourceHandle.startsWith('tube-') || targetHandle.startsWith('tube-');\n \n if (isTubeHandle) {\n if (debug) {\n console.log('Edge deletion blocked: Edge connected to tube handle is not detachable', edgeToRemove);\n }\n return false; // Filter out this deletion\n }\n }\n }\n return true; // Allow all other changes\n });\n \n // Only process changes if there are any after filtering\n if (filteredChanges.length > 0) {\n onEdgesChange(filteredChanges);\n if (!isControlled) {\n localStore.setState({ edges: latestEdgesRef.current as NetworkEdge[] });\n } else {\n externalOnEdgesChange && externalOnEdgesChange(latestEdgesRef.current as NetworkEdge[]);\n }\n }\n }}\n onConnect={onConnect}\n onConnectStart={handleConnectStart}\n onConnectEnd={handleConnectEnd}\n onEdgeUpdate={onEdgeUpdate}\n isValidConnection={isValidConnection}\n onNodeClick={handleNodeClick}\n onNodeDoubleClick={handleNodeDoubleClick}\n onNodeDragStart={handleNodeDragStart}\n onNodeDrag={handleNodeDrag}\n onNodeDragStop={handleNodeDragStop}\n onEdgeClick={handleEdgeClick}\n onInit={onInit}\n nodeTypes={memoizedNodeTypes}\n edgeTypes={memoizedEdgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: true\n }}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\n selectNodesOnDrag={false}\n fitView\n proOptions={{ hideAttribution: true }}\n >\n <Background color={colorMode === 'light' ? '#e5e5e5' : '#2a2a2a'} />\n <Controls />\n <MiniMap />\n <Panel position=\"bottom-right\" className=\"react-networks-attribution\">\n <a\n href=\"https://github.com/MP70/react-networks\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"react-networks-attribution-link\"\n >\n react-networks\n </a>\n </Panel>\n </ReactFlow>\n {showDownloadButton && (\n <button\n className=\"download-button\"\n onClick={onDownload}\n style={{\n position: 'absolute',\n top: downloadButtonPosition.includes('top') ? '10px' : 'auto',\n bottom: downloadButtonPosition.includes('bottom') ? '10px' : 'auto',\n right: downloadButtonPosition.includes('right') ? '10px' : 'auto',\n left: downloadButtonPosition.includes('left') ? '10px' : 'auto',\n zIndex: 1000,\n background: '#374151',\n color: '#e5e7eb',\n border: '1px solid #4b5563',\n borderRadius: '4px',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n ...downloadButtonStyle,\n }}\n >\n {downloadButtonText}\n </button>\n )}\n {selectedNode && (selectedNode.type === 'rack' || selectedNode.type === 'device') && (\n <div\n style={{\n position: 'absolute',\n top: 12,\n right: 12,\n display: 'flex',\n gap: 8,\n zIndex: 2000,\n }}\n >\n <button\n onClick={(e) => { e.preventDefault(); toggleSelectedFace(); }}\n style={{\n background: '#374151',\n color: '#e5e7eb',\n border: '1px solid #4b5563',\n borderRadius: 4,\n padding: '6px 10px',\n fontSize: 11,\n fontFamily: 'monospace',\n cursor: 'pointer',\n }}\n title={(() => {\n const nodeData = selectedNode.data as NetworkNode['data'];\n if (selectedNode.type === 'rack') {\n const face = (nodeData?.face as 'front' | 'rear') || 'front';\n return face === 'front' ? 'Switch to rear' : 'Switch to front';\n } else {\n const hasRear = Array.isArray(nodeData?.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData?.ports) && nodeData.ports.length > 0;\n const view = (nodeData?.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n return view === 'front' ? 'Switch to rear' : 'Switch to front';\n }\n })()}\n >\n {(() => {\n const nodeData = selectedNode.data as NetworkNode['data'];\n if (selectedNode.type === 'rack') {\n const face = (nodeData?.face as 'front' | 'rear') || 'front';\n return face === 'front' ? '⇄ Rear' : '⇄ Front';\n } else {\n const hasRear = Array.isArray(nodeData?.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData?.ports) && nodeData.ports.length > 0;\n const view = (nodeData?.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n return view === 'front' ? '⇄ Rear' : '⇄ Front';\n }\n })()}\n </button>\n </div>\n )}\n </div>\n );\n};\n\nexport const NetworkDiagram: React.FC<NetworkDiagramProps> = (props) => {\n return (\n <ReactFlowProvider>\n <NetworkDiagramInner {...props} />\n </ReactFlowProvider>\n );\n};\n","import { NetworkNode, NetworkEdge } from '../types';\n\ninterface InventoryRackDTO {\n id: string | number;\n name: string;\n status?: { value?: string } | string;\n u_height?: number;\n units?: number;\n facility_id?: string | number;\n serial?: string;\n asset_tag?: string;\n site?: { name?: string } | string;\n role?: { name?: string } | string;\n tenant?: { name?: string } | string;\n}\n\ninterface InventoryDeviceDTO {\n id: string | number;\n name: string;\n status?: { value?: string } | string;\n device_type?: { u_height?: number; model?: string; manufacturer?: { name?: string } };\n model?: string;\n manufacturer?: string;\n device_role?: { name?: string } | string;\n u_height?: number;\n position?: number;\n face?: 'front' | 'rear';\n rack?: { id?: string | number; name?: string } | string | number;\n primary_ip4?: { address?: string } | string;\n primary_ip6?: { address?: string } | string;\n site?: { name?: string } | string;\n}\n\ninterface InventoryCableDTO {\n id: string | number;\n type?: { label?: string };\n bandwidth?: string;\n length?: number;\n color?: string;\n status?: { value?: string } | string;\n termination_a?: { device?: { id?: string | number } | string | number; name?: string } | string;\n termination_b?: { device?: { id?: string | number } | string | number; name?: string } | string;\n}\n\n/**\n * Convert inventory rack data to NetworkNode\n */\nexport const inventoryRackToNetworkNode = (rack: InventoryRackDTO): NetworkNode => {\n return {\n id: `rack-${rack.id}`,\n type: 'rack',\n position: { x: 0, y: 0 },\n data: {\n label: rack.name,\n status: ((typeof rack.status === 'object' && rack.status) ? (rack.status as { value?: string }).value : rack.status) as 'active' | 'inactive' | 'maintenance',\n uHeight: rack.u_height ?? rack.units ?? 42,\n inventoryId: rack.id,\n inventoryType: 'rack',\n facilityId: rack.facility_id,\n serial: rack.serial,\n assetTag: rack.asset_tag,\n site: (typeof rack.site === 'object' && rack.site) ? (rack.site as { name?: string }).name : rack.site,\n role: (typeof rack.role === 'object' && rack.role) ? (rack.role as { name?: string }).name : rack.role,\n tenant: (typeof rack.tenant === 'object' && rack.tenant) ? (rack.tenant as { name?: string }).name : rack.tenant,\n },\n };\n};\n\n/**\n * Convert inventory device data to NetworkNode\n */\nexport const inventoryDeviceToNetworkNode = (device: InventoryDeviceDTO): NetworkNode => {\n return {\n id: `device-${device.id}`,\n type: 'device',\n position: { x: 0, y: 0 },\n parentId: device.rack ? `rack-${(typeof device.rack === 'object' && device.rack ? (device.rack as { id?: string | number }).id : device.rack)}` : undefined,\n extent: device.rack ? 'parent' : undefined,\n data: {\n label: device.name,\n status: ((typeof device.status === 'object' && device.status) ? (device.status as { value?: string }).value : device.status) as 'active' | 'inactive' | 'maintenance',\n deviceType: device.device_type?.model ?? device.model,\n manufacturer: (device.device_type?.manufacturer?.name ?? device.manufacturer),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n role: (typeof device.device_role === 'object' && device.device_role) ? (device.device_role as { name?: string }).name : (device as any).role,\n uHeight: device.device_type?.u_height ?? device.u_height ?? 1,\n uPosition: device.position || 1,\n view: (device.face as 'front' | 'rear') || 'front',\n inventoryId: device.id,\n inventoryType: 'device',\n primaryIp4: (typeof device.primary_ip4 === 'object' && device.primary_ip4) ? (device.primary_ip4 as { address?: string }).address : device.primary_ip4,\n primaryIp6: (typeof device.primary_ip6 === 'object' && device.primary_ip6) ? (device.primary_ip6 as { address?: string }).address : device.primary_ip6,\n site: (typeof device.site === 'object' && device.site) ? (device.site as { name?: string }).name : device.site,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n rack: (typeof device.rack === 'object' && device.rack) ? (device.rack as { name?: string }).name : (device.rack as any),\n },\n };\n};\n\n/**\n * Convert inventory cable data to NetworkEdge\n */\nexport const inventoryCableToNetworkEdge = (cable: InventoryCableDTO): NetworkEdge => {\n const getDeviceId = (term: InventoryCableDTO['termination_a']) => {\n if (!term) return undefined;\n if (typeof term === 'string') return term;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const dev = (term as any).device;\n if (typeof dev === 'object' && dev) return (dev as { id?: string | number }).id;\n return dev as string | number | undefined;\n };\n const termADeviceId = getDeviceId(cable.termination_a);\n const termBDeviceId = getDeviceId(cable.termination_b);\n return {\n id: `cable-${cable.id}`,\n source: `device-${termADeviceId}`,\n target: `device-${termBDeviceId}`,\n type: 'fiber',\n data: {\n bandwidth: cable.type?.label ?? cable.bandwidth,\n length: cable.length || 0,\n color: cable.color,\n inventoryId: cable.id,\n inventoryType: 'cable',\n status: ((typeof cable.status === 'object' && cable.status) ? (cable.status as { value?: string }).value : cable.status),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n terminationA: (typeof cable.termination_a === 'object' && cable.termination_a) ? (cable.termination_a as { name?: string }).name : (cable.termination_a as any),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n terminationB: (typeof cable.termination_b === 'object' && cable.termination_b) ? (cable.termination_b as { name?: string }).name : (cable.termination_b as any),\n },\n };\n};\n\n/**\n * Convert inventory data to network diagram format\n */\nexport const inventoryToNetworkDiagram = (data: {\n racks: InventoryRackDTO[];\n devices: InventoryDeviceDTO[];\n cables: InventoryCableDTO[];\n}): { nodes: NetworkNode[]; edges: NetworkEdge[] } => {\n const nodes: NetworkNode[] = [];\n const edges: NetworkEdge[] = [];\n\n data.racks.forEach(rack => nodes.push(inventoryRackToNetworkNode(rack)));\n data.devices.forEach(device => nodes.push(inventoryDeviceToNetworkNode(device)));\n data.cables.forEach(cable => edges.push(inventoryCableToNetworkEdge(cable)));\n\n return { nodes, edges };\n};\n\n/**\n * Generate simple layout positions for nodes array\n */\nexport const generateLayout = (nodes: NetworkNode[]): NetworkNode[] => {\n const rackNodes = nodes.filter(n => n.type === 'rack');\n const deviceNodes = nodes.filter(n => n.type === 'device');\n const otherNodes = nodes.filter(n => !['rack', 'device'].includes(n.type));\n\n rackNodes.forEach((rack, index) => {\n rack.position = { x: index * 300, y: 100 };\n });\n\n deviceNodes.forEach(device => {\n if (device.parentId) {\n const parentRack = rackNodes.find(r => r.id === device.parentId);\n if (parentRack) {\n const uPosition = device.data.uPosition || 1;\n const uHeight = device.data.uHeight || 1;\n device.position = {\n x: parentRack.position.x + 50,\n y: parentRack.position.y + (uPosition * 20) - (uHeight * 10),\n };\n }\n } else {\n device.position = { x: Math.random() * 400 + 100, y: Math.random() * 200 + 50 };\n }\n });\n\n otherNodes.forEach((node, index) => {\n node.position = { x: index * 150 + 100, y: 300 };\n });\n\n return nodes;\n};\n\n\n","import { NetworkNode, RackConfig, RackDevice, Width } from '../types';\nimport { calculateDevicePositionFromU, findNextAvailableUPosition } from './u-positioning';\n\n/**\n * Configuration options for building nodes from rack schema\n */\nexport interface RackSchemaOptions {\n /** How to handle device placement conflicts */\n conflictPolicy?: 'strict' | 'nearest';\n /** Whether to validate all placements before creating nodes */\n validatePlacements?: boolean;\n /** Custom device type mapping from schema to NetworkNode type */\n deviceTypeMapping?: Record<string, NetworkNode['type']>;\n}\n\n/**\n * Error thrown when device placement conflicts occur in strict mode\n */\nexport class DevicePlacementError extends Error {\n constructor(\n public rackId: string,\n public deviceId: string,\n public uPosition: number,\n public uHeight: number,\n public conflictWith?: string\n ) {\n super(\n `Device placement conflict: ${deviceId} at U${uPosition}-${uPosition + uHeight - 1} in rack ${rackId}${\n conflictWith ? ` conflicts with ${conflictWith}` : ''\n }`\n );\n this.name = 'DevicePlacementError';\n }\n}\n\n/**\n * Validation result for device placement\n */\nexport interface DevicePlacementValidation {\n isValid: boolean;\n conflicts: Array<{\n deviceId: string;\n uPosition: number;\n uHeight: number;\n conflictWith: string;\n }>;\n outOfBounds: Array<{\n deviceId: string;\n uPosition: number;\n uHeight: number;\n rackUHeight: number;\n }>;\n}\n\n/**\n * Validate device placements within a rack schema\n */\nexport function validateRackDevicePlacements(\n rack: RackConfig,\n _options: RackSchemaOptions = {}\n): DevicePlacementValidation {\n const conflicts: DevicePlacementValidation['conflicts'] = [];\n const outOfBounds: DevicePlacementValidation['outOfBounds'] = [];\n \n // Check for out-of-bounds placements\n for (const device of rack.devices) {\n const deviceEnd = device.unit + device.height - 1;\n if (deviceEnd > rack.units) {\n outOfBounds.push({\n deviceId: device.id,\n uPosition: device.unit,\n uHeight: device.height,\n rackUHeight: rack.units,\n });\n }\n }\n \n // Check for device-to-device conflicts\n for (let i = 0; i < rack.devices.length; i++) {\n const deviceA = rack.devices[i];\n const deviceAStart = deviceA.unit;\n const deviceAEnd = deviceA.unit + deviceA.height - 1;\n \n for (let j = i + 1; j < rack.devices.length; j++) {\n const deviceB = rack.devices[j];\n const deviceBStart = deviceB.unit;\n const deviceBEnd = deviceB.unit + deviceB.height - 1;\n \n // Check for overlap using 1a rule (start to start+height-1)\n if (deviceAStart <= deviceBEnd && deviceAEnd >= deviceBStart) {\n conflicts.push({\n deviceId: deviceA.id,\n uPosition: deviceA.unit,\n uHeight: deviceA.height,\n conflictWith: deviceB.id,\n });\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n\n/**\n * Convert a RackDevice to NetworkNode with proper U positioning\n */\nfunction createDeviceNode(\n device: RackDevice,\n rack: NetworkNode,\n options: RackSchemaOptions = {}\n): NetworkNode {\n const { deviceTypeMapping = {} } = options;\n \n // Map device type to NetworkNode type\n const nodeType = deviceTypeMapping[device.type] || 'device';\n \n // Calculate pixel position from U position\n const position = calculateDevicePositionFromU(rack, device.unit, device.height);\n \n \n return {\n id: device.id,\n type: nodeType,\n position,\n parentId: rack.id,\n extent: 'parent',\n data: {\n label: device.name,\n status: 'active', // Default status\n deviceType: device.type,\n uHeight: device.height,\n uPosition: device.unit,\n width: device.width || Width.FULL,\n // view is controlled at node-level; default computed in DeviceNode when absent\n role: device.role, // Pass through the role property\n ports: device.ports,\n rearPorts: device.rearPorts,\n connections: device.connections,\n },\n };\n}\n\n/**\n * Convert a RackConfig to NetworkNode\n */\nfunction createRackNode(rack: RackConfig): NetworkNode {\n return {\n id: rack.id,\n type: 'rack',\n position: rack.position,\n data: {\n label: rack.name,\n status: 'active',\n uHeight: rack.units,\n uNumberingDirection: rack.uNumberingDirection || 'bottom-up',\n customHeaderText: rack.customHeaderText,\n ports: [], // Default empty array, can be overridden\n },\n };\n}\n\n/**\n * Build NetworkNode array from RackConfig array with comprehensive validation\n */\nexport function buildNodesFromRackConfig(\n racks: RackConfig[],\n options: RackSchemaOptions = {}\n): NetworkNode[] {\n const { conflictPolicy = 'strict', validatePlacements = true } = options;\n const nodes: NetworkNode[] = [];\n const deviceNodes: NetworkNode[] = [];\n \n // Validate all racks first if requested\n if (validatePlacements) {\n for (const rack of racks) {\n const validation = validateRackDevicePlacements(rack, options);\n \n if (!validation.isValid) {\n if (conflictPolicy === 'strict') {\n // Report all conflicts and out-of-bounds\n const errors: string[] = [];\n \n validation.conflicts.forEach(conflict => {\n errors.push(\n `Device ${conflict.deviceId} at U${conflict.uPosition}-${conflict.uPosition + conflict.uHeight - 1} conflicts with ${conflict.conflictWith}`\n );\n });\n \n validation.outOfBounds.forEach(bound => {\n errors.push(\n `Device ${bound.deviceId} at U${bound.uPosition}-${bound.uPosition + bound.uHeight - 1} exceeds rack height (${bound.rackUHeight}U)`\n );\n });\n \n throw new DevicePlacementError(\n rack.id,\n validation.conflicts[0]?.deviceId || validation.outOfBounds[0]?.deviceId || 'unknown',\n validation.conflicts[0]?.uPosition || validation.outOfBounds[0]?.uPosition || 1,\n validation.conflicts[0]?.uHeight || validation.outOfBounds[0]?.uHeight || 1\n );\n }\n }\n }\n }\n \n // Create rack nodes first (required for device parent references)\n for (const rack of racks) {\n const rackNode = createRackNode(rack);\n nodes.push(rackNode);\n \n // Create device nodes for this rack\n for (const device of rack.devices) {\n try {\n const deviceNode = createDeviceNode(device, rackNode, options);\n deviceNodes.push(deviceNode);\n } catch (error) {\n if (conflictPolicy === 'strict') {\n throw error;\n } else if (conflictPolicy === 'nearest') {\n // Try to find nearest available position\n const availablePosition = findNextAvailableUPosition(\n rackNode,\n { id: device.id, type: 'device', position: { x: 0, y: 0 }, data: { label: device.name, uHeight: device.height } } as NetworkNode,\n deviceNodes,\n device.unit\n );\n \n if (availablePosition !== device.unit) {\n console.warn(\n `Device ${device.id} moved from U${device.unit} to U${availablePosition} due to conflict`\n );\n \n const adjustedDevice = { ...device, unit: availablePosition };\n const deviceNode = createDeviceNode(adjustedDevice, rackNode, options);\n deviceNodes.push(deviceNode);\n } else {\n throw new DevicePlacementError(rack.id, device.id, device.unit, device.height);\n }\n }\n }\n }\n }\n \n // Add device nodes after all rack nodes\n nodes.push(...deviceNodes);\n \n return nodes;\n}\n\n/**\n * Create a RackConfig from existing NetworkNode data (reverse operation)\n */\nexport function createRackConfigFromNodes(nodes: NetworkNode[]): RackConfig[] {\n const racks: RackConfig[] = [];\n const rackNodes = nodes.filter(node => node.type === 'rack');\n \n for (const rackNode of rackNodes) {\n const deviceNodes = nodes.filter(\n node => node.type === 'device' && node.parentId === rackNode.id\n );\n \n const devices: RackDevice[] = deviceNodes.map(deviceNode => ({\n id: deviceNode.id,\n name: deviceNode.data.label,\n unit: deviceNode.data.uPosition || 1,\n height: deviceNode.data.uHeight || 1,\n type: (deviceNode.data.deviceType as RackDevice['type']) || 'server',\n width: deviceNode.data.width,\n ports: deviceNode.data.ports,\n connections: deviceNode.data.connections,\n }));\n \n racks.push({\n id: rackNode.id,\n name: rackNode.data.label,\n position: rackNode.position,\n units: rackNode.data.uHeight || 42,\n uNumberingDirection: rackNode.data.uNumberingDirection || 'bottom-up',\n customHeaderText: rackNode.data.customHeaderText,\n devices,\n });\n }\n \n return racks;\n}\n\n/**\n * Update device U position in a rack schema\n */\nexport function updateDeviceUPosition(\n racks: RackConfig[],\n rackId: string,\n deviceId: string,\n newUPosition: number\n): RackConfig[] {\n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n return {\n ...rack,\n devices: rack.devices.map(device => {\n if (device.id !== deviceId) return device;\n return { ...device, unit: newUPosition };\n }),\n };\n });\n}\n\n/**\n * Add a device to a rack schema\n */\nexport function addDeviceToRack(\n racks: RackConfig[],\n rackId: string,\n device: RackDevice,\n options: RackSchemaOptions = {}\n): RackConfig[] {\n const { conflictPolicy = 'strict' } = options;\n \n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n // Check for conflicts if in strict mode\n if (conflictPolicy === 'strict') {\n const validation = validateRackDevicePlacements(\n { ...rack, devices: [...rack.devices, device] },\n options\n );\n \n if (!validation.isValid) {\n throw new DevicePlacementError(rackId, device.id, device.unit, device.height);\n }\n }\n \n return {\n ...rack,\n devices: [...rack.devices, device],\n };\n });\n}\n\n/**\n * Remove a device from a rack schema\n */\nexport function removeDeviceFromRack(\n racks: RackConfig[],\n rackId: string,\n deviceId: string\n): RackConfig[] {\n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n return {\n ...rack,\n devices: rack.devices.filter(device => device.id !== deviceId),\n };\n });\n}\n","import { NetworkNode, SpliceConfig, SpliceTrayConfig } from '../types';\nimport { calculateSplicePositionFromNumber, findNextAvailableHolderPosition, HOLDERS_PER_TRAY } from './splice-positioning';\n\n/**\n * Configuration options for building nodes from splice schema\n */\nexport interface SpliceSchemaOptions {\n /** How to handle splice placement conflicts */\n conflictPolicy?: 'strict' | 'nearest';\n /** Whether to validate all placements before creating nodes */\n validatePlacements?: boolean;\n}\n\n/**\n * Error thrown when splice placement conflicts occur in strict mode\n */\nexport class SplicePlacementError extends Error {\n constructor(\n public trayId: string,\n public spliceId: string,\n public holder: number,\n public conflictWith?: string\n ) {\n super(\n `Splice placement conflict: ${spliceId} at holder ${holder} in tray ${trayId}${\n conflictWith ? ` conflicts with ${conflictWith}` : ''\n }`\n );\n this.name = 'SplicePlacementError';\n }\n}\n\n/**\n * Validation result for splice placement\n */\nexport interface SplicePlacementValidation {\n isValid: boolean;\n conflicts: Array<{\n spliceId: string;\n holder: number;\n conflictWith: string;\n }>;\n outOfBounds: Array<{\n spliceId: string;\n holder: number;\n max: number;\n }>;\n}\n\n/**\n * Validate splice placements within a tray schema\n */\nexport function validateSplicePlacements(\n tray: SpliceTrayConfig,\n _options: SpliceSchemaOptions = {}\n): SplicePlacementValidation {\n const conflicts: SplicePlacementValidation['conflicts'] = [];\n const outOfBounds: SplicePlacementValidation['outOfBounds'] = [];\n \n // Check for out-of-bounds placements\n for (const splice of tray.splices) {\n if (splice.holder < 1 || splice.holder > HOLDERS_PER_TRAY) {\n outOfBounds.push({\n spliceId: splice.id,\n holder: splice.holder,\n max: HOLDERS_PER_TRAY,\n });\n }\n }\n \n // Check for splice-to-splice conflicts\n for (let i = 0; i < tray.splices.length; i++) {\n const spliceA = tray.splices[i];\n \n for (let j = i + 1; j < tray.splices.length; j++) {\n const spliceB = tray.splices[j];\n \n // Check if two splices are in the same holder position\n if (spliceA.holder === spliceB.holder) {\n conflicts.push({\n spliceId: spliceA.id,\n holder: spliceA.holder,\n conflictWith: spliceB.id,\n });\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n\n/**\n * Convert a SpliceConfig to NetworkNode with proper holder positioning\n */\nfunction createSpliceNode(\n splice: SpliceConfig,\n tray: NetworkNode\n): NetworkNode {\n // Calculate pixel position from holder position\n const position = calculateSplicePositionFromNumber(tray, splice.holder);\n \n return {\n id: splice.id,\n type: 'splice',\n position,\n parentId: tray.id,\n extent: 'parent',\n data: {\n label: splice.name,\n holderPosition: splice.holder,\n lossDb: splice.lossDb,\n },\n };\n}\n\n/**\n * Convert a SpliceTrayConfig to NetworkNode\n */\nfunction createTrayNode(tray: SpliceTrayConfig): NetworkNode {\n return {\n id: tray.id,\n type: 'splice-tray',\n position: tray.position,\n data: {\n label: tray.name,\n status: 'active',\n },\n };\n}\n\n/**\n * Build NetworkNode array from SpliceTrayConfig array with comprehensive validation\n */\nexport function buildNodesFromSpliceConfig(\n trays: SpliceTrayConfig[],\n options: SpliceSchemaOptions = {}\n): NetworkNode[] {\n const { conflictPolicy = 'strict', validatePlacements = true } = options;\n const nodes: NetworkNode[] = [];\n const spliceNodes: NetworkNode[] = [];\n \n // Validate all trays first if requested\n if (validatePlacements) {\n for (const tray of trays) {\n const validation = validateSplicePlacements(tray, options);\n \n if (!validation.isValid) {\n if (conflictPolicy === 'strict') {\n // Report all conflicts and out-of-bounds\n const errors: string[] = [];\n \n validation.conflicts.forEach(conflict => {\n errors.push(\n `Splice ${conflict.spliceId} at holder ${conflict.holder} conflicts with ${conflict.conflictWith}`\n );\n });\n \n validation.outOfBounds.forEach(bound => {\n errors.push(\n `Splice ${bound.spliceId} at holder ${bound.holder} is out of bounds (max: ${bound.max})`\n );\n });\n \n throw new SplicePlacementError(\n tray.id,\n validation.conflicts[0]?.spliceId || validation.outOfBounds[0]?.spliceId || 'unknown',\n validation.conflicts[0]?.holder || validation.outOfBounds[0]?.holder || 1\n );\n }\n }\n }\n }\n \n // Create tray nodes first (required for splice parent references)\n for (const tray of trays) {\n const trayNode = createTrayNode(tray);\n nodes.push(trayNode);\n \n // Create splice nodes for this tray\n for (const splice of tray.splices) {\n try {\n const spliceNode = createSpliceNode(splice, trayNode);\n spliceNodes.push(spliceNode);\n } catch (error) {\n if (conflictPolicy === 'strict') {\n throw error;\n } else if (conflictPolicy === 'nearest') {\n // Try to find nearest available position\n // Pass all nodes (tray + existing splices) for proper conflict detection\n const allNodesForConflictCheck = [...nodes, ...spliceNodes];\n const availablePosition = findNextAvailableHolderPosition(\n trayNode,\n { id: splice.id, type: 'splice', position: { x: 0, y: 0 }, data: { label: splice.name, holderPosition: splice.holder } } as NetworkNode,\n allNodesForConflictCheck,\n splice.holder\n );\n \n if (availablePosition !== splice.holder) {\n console.warn(\n `Splice ${splice.id} moved from holder ${splice.holder} to holder ${availablePosition} due to conflict`\n );\n \n const adjustedSplice = { ...splice, holder: availablePosition };\n const spliceNode = createSpliceNode(adjustedSplice, trayNode);\n spliceNodes.push(spliceNode);\n } else {\n throw new SplicePlacementError(tray.id, splice.id, splice.holder);\n }\n }\n }\n }\n }\n \n // Add splice nodes after all tray nodes\n nodes.push(...spliceNodes);\n \n return nodes;\n}\n\n/**\n * Create a SpliceTrayConfig from existing NetworkNode data (reverse operation)\n */\nexport function createSpliceConfigFromNodes(nodes: NetworkNode[]): SpliceTrayConfig[] {\n const trays: SpliceTrayConfig[] = [];\n const trayNodes = nodes.filter(node => node.type === 'splice-tray');\n \n for (const trayNode of trayNodes) {\n const spliceNodes = nodes.filter(\n node => node.type === 'splice' && node.parentId === trayNode.id\n );\n \n const splices: SpliceConfig[] = spliceNodes.map(spliceNode => ({\n id: spliceNode.id,\n name: spliceNode.data.label,\n holder: spliceNode.data.holderPosition || 1,\n lossDb: spliceNode.data.lossDb,\n }));\n \n trays.push({\n id: trayNode.id,\n name: trayNode.data.label,\n position: trayNode.position,\n splices,\n });\n }\n \n return trays;\n}\n\n/**\n * Update splice holder position in a splice schema\n */\nexport function updateSpliceHolderPosition(\n trays: SpliceTrayConfig[],\n trayId: string,\n spliceId: string,\n newHolder: number\n): SpliceTrayConfig[] {\n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n return {\n ...tray,\n splices: tray.splices.map(splice => {\n if (splice.id !== spliceId) return splice;\n return { ...splice, holder: newHolder };\n }),\n };\n });\n}\n\n/**\n * Add a splice to a tray schema\n */\nexport function addSpliceToTray(\n trays: SpliceTrayConfig[],\n trayId: string,\n splice: SpliceConfig,\n options: SpliceSchemaOptions = {}\n): SpliceTrayConfig[] {\n const { conflictPolicy = 'strict' } = options;\n \n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n // Check for conflicts if in strict mode\n if (conflictPolicy === 'strict') {\n const validation = validateSplicePlacements(\n { ...tray, splices: [...tray.splices, splice] },\n options\n );\n \n if (!validation.isValid) {\n throw new SplicePlacementError(trayId, splice.id, splice.holder);\n }\n }\n \n return {\n ...tray,\n splices: [...tray.splices, splice],\n };\n });\n}\n\n/**\n * Remove a splice from a tray schema\n */\nexport function removeSpliceFromTray(\n trays: SpliceTrayConfig[],\n trayId: string,\n spliceId: string\n): SpliceTrayConfig[] {\n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n return {\n ...tray,\n splices: tray.splices.filter(splice => splice.id !== spliceId),\n };\n });\n}\n\n"]}
1
+ {"version":3,"sources":["../src/utils/u-positioning.ts","../src/utils/status-colors.ts","../src/components/RackNode.tsx","../src/components/FiberNode.tsx","../src/components/FiberEdge.tsx","../src/components/PowerEdge.tsx","../src/components/SmoothStepFiberEdge.tsx","../src/components/StepFiberEdge.tsx","../src/components/ThickCableEdge.tsx","../src/types/index.ts","../src/utils/power-connectors.ts","../src/components/DeviceNode.tsx","../src/components/VerticalPDU.tsx","../src/components/SpliceNode.tsx","../src/utils/splice-positioning.ts","../src/components/SpliceTrayNode.tsx","../src/utils/fiber-colors.ts","../src/components/TubeNode.tsx","../src/components/CableNode.tsx","../src/components/CouplerNode.tsx","../src/utils/coupler-positioning.ts","../src/components/PatchPanelNode.tsx","../src/components/ClosureNode.tsx","../src/core/store.ts","../src/core/hooks.ts","../src/utils/rack-geometry.ts","../src/utils/edge-connection.ts","../src/components/NetworkDiagram.tsx","../src/utils/inventory.ts","../src/utils/rack-schema.ts","../src/utils/splice-schema.ts"],"names":["getDefaultUNumberingDirection","getRackUNumberingDirection","rack","convertUPositionForDirection","uPosition","rackUHeight","direction","convertUPositionFromDirection","snapToUPosition","device","newPosition","allNodes","uHeight","startY","relativeY","physicalUPosition","calculatedUPosition","maxUPosition","snappedUPosition","isUPositionAvailable","availablePosition","findNextAvailableUPosition","snappedY","topLogicalUPosition","topPhysicalUPosition","snappedPhysicalUPosition","deviceUHeight","rackDevices","node","otherDevice","otherUPosition","otherUHeight","newDeviceStart","newDeviceEnd","otherDeviceStart","otherDeviceEnd","startFrom","u","calculateDevicePositionFromU","deviceHeight","deviceY","updateDeviceUPosition","newUPosition","validateAndSnapDevice","currentUPosition","validUPosition","getStatusColor","status","RackNode","data","selected","id","onViewChange","onRackFaceChange","isDragOver","label","ports","face","customHeaderText","getNodes","setNodes","useReactFlow","nodes","showUMarkers","setShowUMarkers","useState","toggleUNumberingDirection","newDirection","n","toggleFace","next","child","renderUPositions","positions","i","yPos","displayNumber","jsx","jsxs","e","FiberNode","Handle","Position","FiberEdge","sourceX","sourceY","targetX","targetY","sourcePosition","targetPosition","style","_className","edgePath","labelX","labelY","getBezierPath","bandwidth","length","color","striped","baseEdgeStyle","Fragment","BaseEdge","EdgeLabelRenderer","PowerEdge","markerEnd","connectorType","baseStyle","SmoothStepFiberEdge","props","edgeStyle","ReactFlowSmoothStepEdge","getStepPath","_targetPosition","isHorizontalFirst","path","midX","midY","StepFiberEdge","_props","ThickCableEdge","Width","POWER_CONNECTORS","getPowerPortStyle","connector","isHighPower","width","height","cornerStyle","getConnectorConfig","isHighPowerConnector","getPDUPortType","portIndex","getDeviceConnectorType","deviceName","name","DeviceNode","deviceType","manufacturer","role","rearPorts","view","currentFace","handleSideMap","portBlock","port","handleId","rackDeviceWidth","rackDeviceLeft","renderPortsFromArray","portBlocks","position","handles","portWidth","portHeight","_blockIndex","isPower","isConnected","portColor","handlePosition","handleStyle","baseTop","spacing","portStyle","isPatchPanel","handleType","oppositeType","renderHandles","renderAGGSwitchHandles","isSwitch","port1Top","port2Top","handle","bottomIndex","uplinkWidth","uplinkHeight","VerticalPDU","heightCm","powerPorts","widthPx","mgmt_unit","heightPx","renderPowerHandles","nCycles","portsPerCycle","_","c","idx","headerHeight","portSpacing","renderMgmtUnit","portType","leftPx","SpliceNode","lossDb","edges","useEdges","leftEdge","rightEdgeAsSource","rightEdgeAsTarget","rightEdge","leftColor","rightColor","bothConnected","HOLDER_HEIGHT_PX","TRAY_HEADER_HEIGHT","TRAY_BOTTOM_PADDING","HOLDERS_PER_TRAY","SPLICE_WIDTH_PX","TRAY_WIDTH_PX","SPLICE_CENTER_X","snapToSplicePosition","splice","tray","calculatedPosition","snappedPosition","isHolderPositionAvailable","findNextAvailableHolderPosition","pos","calculateSplicePositionFromNumber","holderPosition","spliceY","SpliceTrayNode","showHolderMarkers","setShowHolderMarkers","renderHolderPositions","FIBER_COLORS_12","baseColorFor","normalizedId","isStriped","fiberSolidOrStriped","base","getFiberColor","TubeNode","_id","fibersPerTube","tubeIndex","startOn","fibers","handleSize","handleSpacing","padding","borderWidth","totalHandlesWidth","tubeBorderColor","tubeConnectionHandleId","tubeConnectionHandleSize","connectionHandleStyle","getTubeConnectionPosition","innerWidth","startLeft","reverseColors","fiberIdx","fiberStyle","baseColor","left","top","handleBackground","fiberHandleId","React","CableNode","tubeCount","providedFiberCount","cableId","rawTubeStartIndex","tubes","tubeStartIndex","innerPaddingTop","totalFibers","primaryText","secondaryText","firstTubeColor","cableColor","borderColor","tubeIdx","tubeStyle","tubeHandleId","buttonHandleId","buttonHandleSize","buttonHandleStyle","CouplerNode","couplerFiberCount","portLabelsLeft","portLabelsRight","normalizedFiberCount","portCount","minWidth","minHeight","totalHandlesHeight","getPortColor","side","labels","displayLabel","PANEL_HEADER_HEIGHT","COUPLER_SLOT_HEIGHT_PX","COUPLERS_PER_PANEL","COUPLER_WIDTH_PX","PANEL_WIDTH_PX","PANEL_HEIGHT_PX","PANEL_BORDER_WIDTH","PANEL_PADDING","PANEL_TUBE_TRAY_SPACING","getCouplerDimensions","getTubeDimensions","getTrayDimensions","_node","getNodeDimensions","getPanelWidth","panelNode","getPanelHeight","getInnerContentWidth","calculateCouplerRightX","couplerWidth","calculateSlotPositionFromY","y","slotHeight","calculateYFromSlotPosition","slot","snapToCouplerPosition","coupler","panel","calculatePanelDimensions","childNodes","hasTubes","hasTrays","hasCouplers","handleExtension","tubeWidth","dims","maxRight","childRight","maxBottom","childBottom","calculateCouplerSpacing","numCouplers","couplerHeight","availableHeight","totalCouplerHeight","availableSpacing","spacingBetweenCouplers","calculateCouplerSlotSpacing","CLOSURE_TUBE_TRAY_SPACING","CLOSURE_WIDTH_PX","CLOSURE_HEIGHT_PX","calculateClosureDimensions","closureNode","leftTubeWidth","rightTubeWidth","trayWidth","trays","tubePositions","t","trayPositions","avgTrayX","a","b","tube","PatchPanelNode","header","dataWidth","dataHeight","isUpdatingRef","useRef","useMemo","dynamicDimensions","useEffect","currentWidth","currentHeight","widthDiff","heightDiff","panelWidth","panelHeight","displayHeader","ClosureNode","closureWidth","closureHeight","semicircleRadius","defaultValidateConnection","params","ctx","sourceAlready","targetAlready","sourceHandleId","targetHandleId","sourceNode","targetNode","isPowerHandle","h","looksLikeDevicePower","isPduPower","isNetworkHandle","looksLikeNetwork","isCustomPortName","sourceIsPower","targetIsPower","sourceIsNetwork","targetIsNetwork","isPduSource","isPduTarget","deviceNode","pduNode","eSourceIsPower","eTargetIsPower","involvesDevice","getHandleSide","normalizedHandleId","frontBlocks","rearBlocks","block","createNetworkDiagramStore","initial","options","state","listeners","partial","l","listener","edge","deviceView","targetHandle","targetHandleLc","isStandardNetworkHandle","nodeId","useNetworkDiagram","store","subscribe","cb","getSnapshot","useSyncExternalStore","useNodes","useSelectEdgeZIndex","getRackBounds","rackWidth","rackHeight","rackLeft","rackRight","rackTop","rackBottom","isPointInRack","point","bounds","findNearestRack","racks","nearestRack","minDistance","distance","replaceEdge","connection","edgeType","selectEdgeZIndex","findBy","existingEdge","filtered","edgeFromAddEdge","addEdge","newEdge","zIndex","edgeWithMetadata","createNodeTypes","getDragOverRackId","edgeTypes","NetworkDiagramInner","initialNodes","initialEdges","externalOnNodesChange","externalOnEdgesChange","debug","onNodeClick","onEdgeClick","className","alignRacksToBottom","colorMode","onInit","onFlowMethods","showDownloadButton","downloadButtonPosition","downloadButtonText","downloadButtonStyle","allowReconnectExisting","useSmoothstepEdgesForTubes","isControlled","localStore","storeNodes","storeEdges","reactFlowNodes","onNodesChange","useNodesState","reactFlowEdges","setEdges","onEdgesChange","useEdgesState","reactFlowWrapper","toObject","setViewport","setReactFlowNodes","setReactFlowEdges","toPng","onDownload","useCallback","dataUrl","link","error","dragOverRackId","setDragOverRackId","dragOverRackIdRef","onViewChangeRef","onRackFaceChangeRef","getDragOverRackIdStable","memoizedNodeTypes","rackId","memoizedEdgeTypes","latestNodesRef","latestEdgesRef","rackBottoms","r","minBottom","baselineBottom","nextNodes","currentBottom","delta","getNodeById","deriveFiberColorFromSource","sourceNodeId","sourceHandle","fiberNumStr","fiberNum","tubeNumStr","tubeNum","nodeData","eds","newZIndex","updatedNodes","parentPanel","parentTray","parentRack","index","originalNode","handleNodesChange","changes","updatedChanges","change","updatedNode","snappedResult","rackNode","absoluteX","absoluteY","handleNodeDragStart","_event","handleNodeDrag","_nodes","handleNodeDragStop","relativeX","isValidConnection","validation","onConnect","sourceNodeData","isSwitchSource","looksLikePowerTarget","looksLikeNetworkTarget","isTubeToCable","isCableToTube","isTubeConnection","isButtonHandleConnection","edgeData","colorInfo","newEdges","edgeToAdd","setAnimatingEdges","prev","onEdgeUpdate","oldEdge","newConnection","oldSourceHandle","oldTargetHandle","newSourceHandle","newTargetHandle","handleNodeClick","event","isCommandClick","parentNode","nds","currentView","nextView","handleNodeDoubleClick","handleEdgeClick","selectedNode","setSelectedNode","animatingEdges","useOnSelectionChange","handleConnectStart","handleConnectEnd","toggleSelectedFace","hasRear","hasFront","edgesWithAnimation","sourceSide","targetSide","sourceView","targetView","sourceIsRear","targetIsRear","nextStyle","ReactFlow","filteredChanges","edgeToRemove","Background","Controls","MiniMap","Panel","NetworkDiagram","ReactFlowProvider","inventoryRackToNetworkNode","inventoryDeviceToNetworkNode","inventoryCableToNetworkEdge","cable","getDeviceId","term","dev","termADeviceId","termBDeviceId","inventoryToNetworkDiagram","generateLayout","rackNodes","deviceNodes","otherNodes","DevicePlacementError","deviceId","conflictWith","validateRackDevicePlacements","_options","conflicts","outOfBounds","deviceA","deviceAStart","deviceAEnd","j","deviceB","deviceBStart","deviceBEnd","createDeviceNode","deviceTypeMapping","nodeType","createRackNode","buildNodesFromRackConfig","conflictPolicy","validatePlacements","errors","conflict","bound","adjustedDevice","createRackConfigFromNodes","devices","addDeviceToRack","removeDeviceFromRack","SplicePlacementError","trayId","spliceId","holder","validateSplicePlacements","spliceA","spliceB","createSpliceNode","createTrayNode","buildNodesFromSpliceConfig","spliceNodes","trayNode","spliceNode","allNodesForConflictCheck","adjustedSplice","createSpliceConfigFromNodes","trayNodes","splices","updateSpliceHolderPosition","newHolder","addSpliceToTray","removeSpliceFromTray"],"mappings":"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","file":"index.mjs","sourcesContent":["import { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\n\n/**\n * Get the default U numbering direction\n */\nexport const getDefaultUNumberingDirection = (): UNumberingDirection => 'bottom-up';\n\n/**\n * Get the U numbering direction for a rack\n */\nexport const getRackUNumberingDirection = (rack: NetworkNode): UNumberingDirection => {\n return rack.data.uNumberingDirection || getDefaultUNumberingDirection();\n};\n\n/**\n * Convert U position number based on numbering direction\n * For bottom-up: U position 1 is at the bottom\n * For top-down: U position 1 is at the top\n */\nexport const convertUPositionForDirection = (\n uPosition: number,\n rackUHeight: number,\n direction: UNumberingDirection\n): number => {\n if (direction === 'bottom-up') {\n // For bottom-up, U position 1 is at the bottom, so we need to flip the numbering\n return rackUHeight - uPosition + 1;\n }\n // For top-down, U position 1 is at the top, so no conversion needed\n return uPosition;\n};\n\n/**\n * Convert U position number back to physical position\n */\nexport const convertUPositionFromDirection = (\n uPosition: number,\n rackUHeight: number,\n direction: UNumberingDirection\n): number => {\n if (direction === 'bottom-up') {\n // For bottom-up, convert back from the flipped numbering\n return rackUHeight - uPosition + 1;\n }\n // For top-down, no conversion needed\n return uPosition;\n};\n\n/**\n * Calculate U position from device Y coordinate within a rack\n */\nexport const calculateUPositionFromY = (\n deviceY: number,\n rackY: number,\n rackUHeight: number = 42,\n direction: UNumberingDirection = 'bottom-up'\n): number => {\n const startY = RACK_HEADER_HEIGHT; // Start at top of rack body\n const relativeY = deviceY - rackY - startY;\n const physicalUPosition = Math.max(1, Math.min(rackUHeight, Math.round(relativeY / U_HEIGHT_PX) + 1));\n \n // Convert to the appropriate numbering direction\n return convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n};\n\n/**\n * Snap a device position to the nearest U position within a rack\n */\nexport const snapToUPosition = (\n device: NetworkNode,\n rack: NetworkNode,\n newPosition: { x: number; y: number },\n allNodes: NetworkNode[]\n): { x: number; y: number; uPosition?: number } => {\n if (!device.parentId || device.parentId !== rack.id) {\n return newPosition;\n }\n\n const uHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n const direction = getRackUNumberingDirection(rack);\n \n // Calculate U position based on Y coordinate\n const startY = RACK_HEADER_HEIGHT; // After header\n \n // Calculate which U position this corresponds to\n // Y coordinate represents the MIDDLE of the device for better drag behavior\n const relativeY = newPosition.y - startY; // child position is already parent-relative\n const physicalUPosition = Math.round(relativeY / U_HEIGHT_PX) + 1;\n \n // Convert to logical U position based on direction\n // For snapping, we want to find the U position that corresponds to the Y position\n // The Y position represents where the user wants to place the device\n let calculatedUPosition;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // But the Y position represents the TOP of the device\n // So we need to adjust for the device height\n const logicalPosition = convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n calculatedUPosition = logicalPosition - uHeight + 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n const logicalPosition = convertUPositionForDirection(physicalUPosition, rackUHeight, direction);\n calculatedUPosition = logicalPosition;\n }\n \n // Ensure the device doesn't extend beyond the rack boundaries\n // For multi-U devices, we need to ensure the entire device fits\n const maxUPosition = rackUHeight - uHeight + 1;\n let snappedUPosition = Math.max(1, Math.min(maxUPosition, calculatedUPosition));\n \n // For top-down numbering, ensure we can place devices at the top (U1)\n if (direction === 'top-down' && calculatedUPosition <= 1) {\n snappedUPosition = 1;\n }\n \n // Debug logging (commented out for production)\n // console.log('SnapToUPosition Debug:', {\n // deviceId: device.id,\n // newPosition,\n // rackPosition: rack.position,\n // startY,\n // relativeY,\n // physicalUPosition,\n // calculatedUPosition,\n // snappedUPosition,\n // uHeight,\n // rackUHeight,\n // direction\n // });\n \n // Check if the calculated position is available, if not find the nearest available position\n if (!isUPositionAvailable(rack, device, snappedUPosition, allNodes)) {\n // Try to find the nearest available position\n const availablePosition = findNextAvailableUPosition(rack, device, allNodes, snappedUPosition);\n if (availablePosition !== snappedUPosition) {\n snappedUPosition = availablePosition;\n }\n }\n \n // Snap to exact U position - ensure devices are exactly on U boundaries\n // Account for device border (1px) to align properly with U grid\n // The Y coordinate should ALWAYS represent the TOP of the device\n // For bottom-up direction, we need to calculate the Y position of the TOP of the device\n let snappedY;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // So we need to calculate the Y position of the TOP of the device\n const topLogicalUPosition = snappedUPosition + uHeight - 1;\n const topPhysicalUPosition = convertUPositionFromDirection(topLogicalUPosition, rackUHeight, direction);\n snappedY = startY + (topPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n const snappedPhysicalUPosition = convertUPositionFromDirection(snappedUPosition, rackUHeight, direction);\n snappedY = startY + (snappedPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n }\n \n return {\n x: newPosition.x,\n y: snappedY,\n uPosition: snappedUPosition,\n };\n};\n\n/**\n * Check if a U position is available in a rack\n */\nexport const isUPositionAvailable = (\n rack: NetworkNode,\n device: NetworkNode,\n uPosition: number,\n allNodes: NetworkNode[]\n): boolean => {\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n // Check bounds\n if (uPosition < 1 || uPosition + deviceUHeight - 1 > rackUHeight) {\n return false;\n }\n \n // Check for conflicts with other devices in the same rack\n const rackDevices = allNodes.filter(node => \n node.type === 'device' && \n node.parentId === rack.id && \n node.id !== device.id\n );\n \n for (const otherDevice of rackDevices) {\n const otherUPosition = otherDevice.data.uPosition || 1;\n const otherUHeight = otherDevice.data.uHeight || 1;\n \n // Check if the new device would overlap with existing device\n const newDeviceStart = uPosition;\n const newDeviceEnd = uPosition + deviceUHeight - 1;\n const otherDeviceStart = otherUPosition;\n const otherDeviceEnd = otherUPosition + otherUHeight - 1;\n \n if (newDeviceStart <= otherDeviceEnd && newDeviceEnd >= otherDeviceStart) {\n return false; // Overlap detected\n }\n }\n \n return true;\n};\n\n/**\n * Find the next available U position in a rack\n */\nexport const findNextAvailableUPosition = (\n rack: NetworkNode,\n device: NetworkNode,\n allNodes: NetworkNode[],\n startFrom: number = 1\n): number => {\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n for (let u = startFrom; u <= rackUHeight - deviceUHeight + 1; u++) {\n if (isUPositionAvailable(rack, device, u, allNodes)) {\n return u;\n }\n }\n \n return 1; // Fallback to position 1\n};\n\n/**\n * Calculate device position based on U position within a rack\n */\nexport const calculateDevicePositionFromU = (\n rack: NetworkNode,\n uPosition: number,\n deviceHeight: number = 1\n): { x: number; y: number } => {\n const startY = RACK_HEADER_HEIGHT; // After header\n const direction = getRackUNumberingDirection(rack);\n const rackUHeight = rack.data.uHeight || 42;\n \n // Convert U position to physical position\n const physicalUPosition = convertUPositionFromDirection(uPosition, rackUHeight, direction);\n \n // Position device so its TOP edge aligns with the U position\n // For initial positioning, we place the device at the exact U position specified\n let deviceY;\n if (direction === 'bottom-up') {\n // For bottom-up, the logical U position represents the BOTTOM of the device\n // So we need to calculate the Y position of the TOP of the device\n const topLogicalUPosition = uPosition + deviceHeight - 1;\n const topPhysicalUPosition = convertUPositionFromDirection(topLogicalUPosition, rackUHeight, direction);\n deviceY = startY + (topPhysicalUPosition - 1) * U_HEIGHT_PX - 1;\n } else {\n // For top-down, the logical U position represents the TOP of the device\n deviceY = startY + (physicalUPosition - 1) * U_HEIGHT_PX - 1;\n }\n \n return {\n x: 0, // Align with rack left edge (relative to parent)\n y: deviceY,\n };\n};\n\n/**\n * Update device U position and recalculate position\n */\nexport const updateDeviceUPosition = (\n device: NetworkNode,\n rack: NetworkNode,\n newUPosition: number\n): NetworkNode => {\n const deviceHeight = device.data.uHeight || 1;\n const newPosition = calculateDevicePositionFromU(rack, newUPosition, deviceHeight);\n \n return {\n ...device,\n position: newPosition,\n data: {\n ...device.data,\n uPosition: newUPosition,\n },\n };\n};\n\n/**\n * Validate and snap device to valid U position\n */\nexport const validateAndSnapDevice = (\n device: NetworkNode,\n rack: NetworkNode\n): NetworkNode => {\n const currentUPosition = device.data.uPosition || 1;\n const deviceUHeight = device.data.uHeight || 1;\n const rackUHeight = rack.data.uHeight || 42;\n \n // Ensure U position is within bounds\n const validUPosition = Math.max(1, Math.min(rackUHeight - deviceUHeight + 1, currentUPosition));\n \n if (validUPosition !== currentUPosition) {\n return updateDeviceUPosition(device, rack, validUPosition);\n }\n \n return device;\n};\n","import { DeviceStatus } from '../types';\n\n/**\n * Get the color code for a device status\n * @param status - The device status\n * @returns Hex color code for the status\n * @public\n */\nexport function getStatusColor(status: DeviceStatus | string): string {\n switch (status) {\n case 'active':\n return '#10b981';\n case 'inactive':\n return '#6b7280';\n case 'maintenance':\n return '#f59e0b';\n default:\n return '#6b7280';\n }\n}\n\n","import React, { useState } from 'react';\nimport { NodeProps, useReactFlow } from 'reactflow';\nimport { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT, RACK_WIDTH_PX } from '../utils/constants';\nimport { getRackUNumberingDirection, convertUPositionForDirection } from '../utils/u-positioning';\nimport { getStatusColor } from '../utils/status-colors';\n\ninterface RackNodeProps extends NodeProps<NetworkNode['data']> {\n onViewChange?: (nodeId: string, view: 'front' | 'rear') => void;\n onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void;\n isDragOver?: boolean;\n}\n\nexport const RackNode: React.FC<RackNodeProps> = ({ data, selected, id, onViewChange, onRackFaceChange, isDragOver = false }) => {\n const { \n label, \n ports = 0, \n status = 'active',\n uHeight = 42, // Standard rack height\n face = 'front',\n customHeaderText\n } = data;\n \n const { getNodes, setNodes } = useReactFlow();\n const nodes = getNodes();\n const [showUMarkers, setShowUMarkers] = useState(true);\n \n const toggleUNumberingDirection = () => {\n const currentDirection = getRackUNumberingDirection({ data } as NetworkNode);\n const newDirection: UNumberingDirection = currentDirection === 'bottom-up' ? 'top-down' : 'bottom-up';\n \n setNodes(nodes => nodes.map(n => \n n.id === id \n ? { ...n, data: { ...n.data, uNumberingDirection: newDirection } }\n : n\n ));\n };\n\n \n const toggleFace = () => {\n const next = face === 'front' ? 'rear' : 'front';\n \n if (onRackFaceChange) {\n onRackFaceChange(id, next);\n // Also update child devices via onViewChange if provided\n if (onViewChange) {\n const childNodes = nodes.filter(n => n.parentId === id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n }\n } else if (onViewChange) {\n // Use external onViewChange for devices\n const childNodes = nodes.filter(n => n.parentId === id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n } else {\n // Fallback to internal state management\n setNodes(nodes => nodes.map(n => \n n.id === id \n ? { ...n, data: { ...n.data, face: next } }\n : n.parentId === id \n ? { ...n, data: { ...n.data, view: next } } // Use 'view' for devices\n : n\n ));\n }\n };\n\n // Generate U position markers aligned to rack origin\n const renderUPositions = () => {\n const positions = [];\n const startY = RACK_HEADER_HEIGHT; // Start after header from rack origin\n const direction = getRackUNumberingDirection({ data } as NetworkNode);\n \n for (let i = 1; i <= uHeight; i++) {\n const yPos = startY + (i - 1) * U_HEIGHT_PX - 4; // Align with device positioning, shifted up 3px\n // Convert the physical position to the display number based on direction\n const displayNumber = convertUPositionForDirection(i, uHeight, direction);\n \n positions.push(\n <div\n key={i}\n style={{\n position: 'absolute',\n left: '-35px',\n top: `${yPos}px`,\n background: '#374151',\n color: '#9ca3af',\n padding: '2px 4px',\n borderRadius: '2px',\n fontSize: '8px',\n fontWeight: 'bold',\n width: '28px',\n textAlign: 'center',\n border: '1px solid #4b5563',\n zIndex: 10,\n height: `${U_HEIGHT_PX}px`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n >\n {displayNumber}\n </div>\n );\n }\n return positions;\n };\n\n\n return (\n <div\n className={`rack-node ${selected ? 'selected' : ''} ${isDragOver ? 'drag-over' : ''}`}\n style={{\n background: 'transparent',\n border: `2px solid ${getStatusColor(status)}`,\n borderRadius: '8px',\n padding: 0,\n width: `${RACK_WIDTH_PX}px`, // Fixed width for parent node\n height: `${RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX}px`, // Header + exact U area\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: isDragOver \n ? '0 0 20px #3b82f6, 0 0 40px #3b82f6, 0 0 60px #3b82f6' \n : selected \n ? '0 0 0 2px #3b82f6' \n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n transition: 'box-shadow 0.2s ease-in-out',\n }}\n >\n {/* Rack Header */}\n <div style={{ \n textAlign: 'center', \n marginBottom: 0, \n zIndex: 2, \n background: '#1f2937', \n padding: '8px',\n position: 'relative',\n height: `${RACK_HEADER_HEIGHT}px`, // Fixed header height\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n }}>\n <div style={{ fontWeight: 'bold', marginBottom: '4px' }}>{label}</div>\n <div style={{ fontSize: '10px', color: '#9ca3af' }}>\n {customHeaderText ? (\n <span style={{ color: '#fbbf24', fontWeight: 'bold' }}>{customHeaderText}</span>\n ) : (\n <span>{typeof ports === 'number' ? ports : 0} ports</span>\n )} • {uHeight}U • {face}\n </div>\n <div style={{ display: 'flex', gap: '4px', position: 'absolute', top: '4px', right: '4px' }}>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); setShowUMarkers(!showUMarkers); }}\n style={{\n background: showUMarkers ? '#10b981' : '#374151',\n color: showUMarkers ? '#ffffff' : '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`${showUMarkers ? 'Hide' : 'Show'} U markers`}\n >\n U\n </button>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); toggleUNumberingDirection(); }}\n style={{\n background: '#374151',\n color: '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`Switch U numbering to ${getRackUNumberingDirection({ data } as NetworkNode) === 'bottom-up' ? 'top-down' : 'bottom-up'}`}\n >\n {getRackUNumberingDirection({ data } as NetworkNode) === 'bottom-up' ? '↑↓' : '↓↑'}\n </button>\n <button\n onPointerDown={(e) => { e.stopPropagation(); }}\n onMouseDown={(e) => { e.stopPropagation(); }}\n onClick={(e) => { e.stopPropagation(); e.preventDefault(); toggleFace(); }}\n style={{\n background: '#374151',\n color: '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`Switch to ${face === 'front' ? 'rear' : 'front'} view`}\n >\n {face === 'front' ? '⇄ Rear' : '⇄ Front'}\n </button>\n </div>\n </div>\n \n {/* Rack Body - transparent background; devices are positioned relative to rack origin */}\n <div\n style={{\n flex: 1,\n background: 'transparent',\n // no borders to avoid pixel offsets\n position: 'relative',\n minHeight: `${uHeight * U_HEIGHT_PX}px`,\n overflow: 'hidden',\n }}\n />\n\n {/* Overlay for U markers aligned to rack origin */}\n {showUMarkers && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n }}\n >\n {renderUPositions()}\n </div>\n )}\n \n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\n\nexport const FiberNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { label, status = 'active' } = data;\n\n return (\n <div\n className={`fiber-node ${selected ? 'selected' : ''}`}\n style={{\n background: '#1f2937',\n border: `2px solid ${getStatusColor(status)}`,\n borderRadius: '50%',\n width: '60px',\n height: '60px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '10px',\n fontWeight: 'bold',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n }}\n >\n <Handle type=\"target\" position={Position.Top} />\n <Handle type=\"source\" position={Position.Bottom} />\n <Handle type=\"target\" position={Position.Left} />\n <Handle type=\"source\" position={Position.Right} />\n \n <div style={{ textAlign: 'center' }}>\n <div style={{ fontSize: '8px', lineHeight: '1.2' }}>{label}</div>\n </div>\n \n <div\n style={{\n position: 'absolute',\n bottom: '4px',\n left: '50%',\n transform: 'translateX(-50%)',\n width: '8px',\n height: '8px',\n background: getStatusColor(status),\n borderRadius: '50%',\n }}\n />\n </div>\n );\n};\n","import React from 'react';\nimport { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\nexport const FiberEdge: React.FC<EdgeProps<NetworkEdge['data']> & { className?: string }> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n style = {},\n className: _className,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n const { bandwidth, length, color = '#00FFFF', striped = false } = data || {};\n\n // Use BaseEdge so React Flow layering/zIndex works consistently like power edges\n // Spread style first, then override with our specific properties to ensure data color takes precedence\n const baseEdgeStyle = {\n ...style, // includes zIndex from React Flow\n stroke: color, // Override any stroke from style prop with our data color\n strokeWidth: selected ? 3 : 2,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n\n return (\n <>\n {/* Base colored stroke */}\n <BaseEdge \n id={id} \n path={edgePath} \n style={baseEdgeStyle}\n />\n {/* Overlay black dashed stroke to simulate tracer for 13–24 */}\n {striped && (\n <BaseEdge\n id={`${id}-stripe`}\n path={edgePath}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1.5,\n strokeDasharray: '6 6',\n opacity: 0.9,\n }}\n />\n )}\n <EdgeLabelRenderer>\n {selected && data && (bandwidth || length) && (\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n background: '#1f2937',\n padding: '4px 8px',\n borderRadius: '4px',\n fontSize: '10px',\n color: 'white',\n fontFamily: 'monospace',\n border: `1px solid ${color}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {bandwidth && <div>{bandwidth}</div>}\n {length && <div>{length}m</div>}\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\n};\n","import React from 'react';\nimport { EdgeProps, getBezierPath, BaseEdge } from 'reactflow';\n\nexport const PowerEdge: React.FC<EdgeProps> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n}) => {\n const [edgePath] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Determine connector type based on data\n const connectorType = data?.connectorType || 'C13';\n\n // Different styling for different connector types\n const getEdgeStyle = () => {\n const baseStyle = {\n stroke: data?.color || '#f59e0b',\n strokeWidth: connectorType === 'C19' ? 5 : 3, // Thicker for C19 (higher power)\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n ...style, // This includes zIndex from React Flow\n };\n\n\n // C19 (16A) gets solid line, C13 (10A) gets dashed\n if (connectorType === 'C19') {\n return {\n ...baseStyle,\n strokeDasharray: 'none', // Solid line for high power\n };\n } else {\n return {\n ...baseStyle,\n strokeDasharray: '6,3', // Dashed line for standard power\n };\n }\n };\n\n return (\n <BaseEdge\n id={id}\n path={edgePath}\n markerEnd={markerEnd}\n style={getEdgeStyle()}\n />\n );\n};\n","import React from 'react';\nimport { EdgeProps, SmoothStepEdge as ReactFlowSmoothStepEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * SmoothStepFiberEdge\n * - Wrapper around React Flow's SmoothStepEdge that applies color from edge data\n * - Used for cable-to-tube connections\n */\nexport const SmoothStepFiberEdge: React.FC<EdgeProps<NetworkEdge['data']>> = ({\n data,\n selected,\n style = {},\n ...props\n}) => {\n const { color = '#00FFFF' } = data || {};\n\n // Apply color from data to the edge style\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: selected ? 4 : 3,\n } as React.CSSProperties;\n\n return (\n <ReactFlowSmoothStepEdge\n {...props}\n data={data}\n selected={selected}\n style={edgeStyle}\n />\n );\n};\n\n","import React from 'react';\nimport { EdgeProps, BaseEdge, Position } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * Calculate a step path (right-angle path) between two points\n * The path goes horizontally first, then vertically (or vice versa)\n */\nfunction getStepPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition: _targetPosition,\n}: {\n sourceX: number;\n sourceY: number;\n targetX: number;\n targetY: number;\n sourcePosition: Position;\n targetPosition: Position;\n}): string {\n // Calculate the midpoint for the step\n // For step edges, we go horizontally first, then vertically\n const isHorizontalFirst = sourcePosition === Position.Left || sourcePosition === Position.Right;\n \n let path: string;\n \n if (isHorizontalFirst) {\n // Go horizontal first, then vertical\n const midX = (sourceX + targetX) / 2;\n path = `M ${sourceX},${sourceY} L ${midX},${sourceY} L ${midX},${targetY} L ${targetX},${targetY}`;\n } else {\n // Go vertical first, then horizontal\n const midY = (sourceY + targetY) / 2;\n path = `M ${sourceX},${sourceY} L ${sourceX},${midY} L ${targetX},${midY} L ${targetX},${targetY}`;\n }\n \n return path;\n}\n\n/**\n * StepFiberEdge\n * - Custom step edge that applies color from edge data\n * - Used for tube-to-cable connections\n * - Supports striped edges for fibers 13-24\n */\nexport const StepFiberEdge: React.FC<EdgeProps<NetworkEdge['data']>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n style = {},\n ..._props\n}) => {\n const { color = '#00FFFF', striped = false } = data || {};\n\n // Calculate step path\n const edgePath = getStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Apply color from data to the edge style\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: selected ? 3 : 2,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n return (\n <>\n {/* Base colored stroke */}\n <BaseEdge\n id={id}\n path={edgePath}\n style={edgeStyle}\n />\n {/* Overlay black dashed stroke to simulate tracer for 13–24 */}\n {striped && (\n <BaseEdge\n id={`${id}-stripe`}\n path={edgePath}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1.5,\n strokeDasharray: '6 6',\n opacity: 0.9,\n }}\n />\n )}\n </>\n );\n};\n\n","import React from 'react';\nimport { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from 'reactflow';\n\n/**\n * ThickCableEdge\n * - Thick edge for cable-to-cable connections\n * - Used for connecting cables via button handles\n * - Supports label display\n * - Color comes from edge data (set by NetworkDiagram onConnect)\n */\nexport const ThickCableEdge: React.FC<EdgeProps> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n markerEnd,\n selected,\n}) => {\n const { color = '#6366f1', label } = data || {};\n\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Use same pattern as other edges - spread style first, then override with our properties\n const edgeStyle = {\n ...style, // This includes zIndex from React Flow\n stroke: color, // Override any stroke from style prop with our data color\n strokeWidth: 8, // Thick line for cable connections\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n strokeDasharray: 'none', // Solid line\n } as React.CSSProperties;\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n markerEnd={markerEnd}\n style={edgeStyle}\n />\n {label && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n background: '#1f2937',\n padding: '4px 8px',\n borderRadius: '4px',\n fontSize: '10px',\n color: 'white',\n fontFamily: 'monospace',\n border: `1px solid ${color}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {label}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n};\n\n","/**\n * Rack device width configuration\n * @public\n */\nexport enum Width {\n /** Full width device (19\" rack width) */\n FULL = 'full',\n /** Half width device (9.5\" rack width) */\n HALF = 'half'\n}\n\n/**\n * Port configuration for network devices\n * @public\n */\nexport interface Port {\n /** Display label for the port */\n label: string;\n /** Whether the port is currently connected */\n connected: boolean;\n /** Type of port for styling and validation */\n type?: 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';\n /** Cable type for connection validation */\n cableType?: 'smf' | 'cat6' | 'om3' | 'om4' | 'om5' | 'cat5e' | 'cat6a' | 'cat7' | 'fiber' | 'ethernet';\n}\n\n/**\n * Group of related ports on a device\n * @public\n */\nexport interface PortBlock {\n /** Name of the port group */\n name: string;\n /** Array of ports in this group */\n ports: Port[];\n}\n\n/**\n * Network node types supported by the diagram\n * @public\n */\nexport type NetworkNodeType = \n | 'rack' \n | 'switch' \n | 'router' \n | 'server' \n | 'fiber' \n | 'patch-panel' \n | 'device' \n | 'vertical-pdu'\n | 'splice'\n | 'splice-tray'\n | 'tube'\n | 'cable'\n | 'coupler'\n | 'closure';\n\n/**\n * Device status states\n * @public\n */\nexport type DeviceStatus = 'active' | 'inactive' | 'maintenance';\n\n/**\n * Device view orientations\n * @public\n */\nexport type DeviceView = 'front' | 'rear';\n\n/**\n * Power port side configuration\n * @public\n */\nexport type PowerSide = 'left' | 'right';\n\n/**\n * U numbering direction for racks\n * @public\n */\nexport type UNumberingDirection = 'bottom-up' | 'top-down';\n\n/**\n * Network node data structure\n * @public\n */\nexport interface NetworkNode {\n /** Unique identifier for the node */\n id: string;\n /** Type of network node */\n type: NetworkNodeType;\n /** Position coordinates in the diagram */\n position: { x: number; y: number };\n /** Parent node ID for React Flow sub-flows */\n parentId?: string;\n /** Node extent for sub-flows */\n extent?: 'parent' | [[number, number], [number, number]];\n /** Node data and configuration */\n data: {\n /** Display label for the node */\n label: string;\n /** Port configurations for the device */\n ports?: PortBlock[];\n /** List of connected node IDs */\n connections?: string[];\n /** Current status of the device */\n status?: DeviceStatus;\n /** NetBox integration ID */\n netboxId?: number;\n /** NetBox object type */\n netboxType?: 'device' | 'rack' | 'interface' | 'cable';\n /** Rack height in U units */\n uHeight?: number;\n /** Device position within rack in U units */\n uPosition?: number;\n /** Current view orientation */\n view?: DeviceView;\n /** Device type specification */\n deviceType?: string;\n /** Device manufacturer */\n manufacturer?: string;\n /** Device role in network */\n role?: string;\n /** Device width configuration */\n width?: Width;\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** Power port side for rear view */\n powerSide?: PowerSide;\n /** Vertical PDU height in centimeters */\n heightCm?: number;\n /** Number of AC power ports */\n powerPorts?: number;\n /** U numbering direction for rack nodes */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack nodes */\n customHeaderText?: string;\n /** Holder position within tray (1-12) for splice nodes */\n holderPosition?: number;\n /** Loss value in dB for splice nodes */\n lossDb?: number;\n /** Connector type for coupler nodes */\n connector?: 'SC' | 'LC';\n /** Number of fibers for coupler nodes (1, 2, or 4) */\n couplerFiberCount?: 1 | 2 | 4;\n /** Optional port labels for left side of coupler */\n portLabelsLeft?: string[];\n /** Optional port labels for right side of coupler */\n portLabelsRight?: string[];\n /** Slot position for couplers inside panels (1-based, vertical slots aligned to right edge) */\n slotPosition?: number;\n /** Width override for container nodes (patch-panel, closure) */\n panelWidth?: number;\n /** Height override for container nodes (patch-panel, closure) */\n panelHeight?: number;\n /** Number of rows for container nodes (patch-panel, closure) */\n rows?: number;\n /** Number of columns for container nodes (patch-panel, closure) */\n cols?: number;\n /** Header text for container nodes */\n header?: string;\n /** Additional custom properties */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n };\n}\n\n/**\n * Network edge types\n * @public\n */\nexport type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable';\n\n/**\n * Network edge data structure\n * @public\n */\nexport interface NetworkEdge {\n /** Unique identifier for the edge */\n id: string;\n /** Source node ID */\n source: string;\n /** Target node ID */\n target: string;\n /** Source handle/port ID */\n sourceHandle?: string;\n /** Target handle/port ID */\n targetHandle?: string;\n /** Type of network connection */\n type?: NetworkEdgeType;\n /** Edge data and configuration */\n data?: {\n /** Connection bandwidth */\n bandwidth?: string;\n /** Cable length */\n length?: number;\n /** Edge color for styling */\n color?: string;\n /** Edge kind for styling/validation */\n kind?: 'fiber' | 'power' | 'network';\n /** Additional custom properties */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n };\n}\n\n/**\n * Rack device types\n * @public\n */\nexport type RackDeviceType = 'server' | 'switch' | 'router' | 'patch-panel' | 'ups';\n\n/**\n * Rack configuration structure\n * @public\n */\nexport interface RackConfig {\n /** Unique rack identifier */\n id: string;\n /** Rack display name */\n name: string;\n /** Rack position coordinates */\n position: { x: number; y: number };\n /** Rack height in U units */\n units: number;\n /** U numbering direction (default: 'bottom-up') */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack */\n customHeaderText?: string;\n /** Devices mounted in the rack */\n devices: RackDevice[];\n}\n\n/**\n * Device mounted in a rack\n * @public\n */\nexport interface RackDevice {\n /** Unique device identifier */\n id: string;\n /** Device display name */\n name: string;\n /** Starting U position in rack */\n unit: number;\n /** Device height in U units */\n height: number;\n /** Device type */\n type: RackDeviceType;\n /** Device width configuration */\n width?: Width;\n /** Device role in network */\n role?: string;\n /** Front port configurations */\n ports?: PortBlock[];\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** Power port side for rear view */\n powerSide?: PowerSide;\n /** Connected device IDs */\n connections?: string[];\n}\n\n/**\n * Fiber cable types\n * @public\n */\nexport type FiberCableType = 'single-mode' | 'multi-mode';\n\n/**\n * Fiber cable configuration\n * @public\n */\nexport interface FiberCable {\n /** Unique cable identifier */\n id: string;\n /** Cable display name */\n name: string;\n /** Fiber cable type */\n type: FiberCableType;\n /** Cable length */\n length: number;\n /** Cable color for visualization */\n color: string;\n /** Connection endpoints */\n connections: {\n /** Source connection point */\n from: string;\n /** Target connection point */\n to: string;\n };\n}\n\n/**\n * Splice configuration structure\n * @public\n */\nexport interface SpliceConfig {\n /** Unique splice identifier */\n id: string;\n /** Splice display name */\n name: string;\n /** Holder position within tray (1-12) */\n holder: number;\n /** Loss value in dB */\n lossDb?: number;\n}\n\n/**\n * Splice tray configuration structure\n * @public\n */\nexport interface SpliceTrayConfig {\n /** Unique tray identifier */\n id: string;\n /** Tray display name */\n name: string;\n /** Tray position coordinates */\n position: { x: number; y: number };\n /** Splices in this tray */\n splices: SpliceConfig[];\n}\n\n// Inventory/CMDB integrations are generic and not tied to specific vendors\n\n/**\n * Network diagram component props\n * @public\n */\nexport interface NetworkDiagramProps {\n /** Controlled nodes array */\n nodes?: NetworkNode[];\n /** Controlled edges array */\n edges?: NetworkEdge[];\n /** Callback when nodes change (controlled mode) */\n onNodesChange?: (nodes: NetworkNode[]) => void;\n /** Callback when edges change (controlled mode) */\n onEdgesChange?: (edges: NetworkEdge[]) => void;\n /** Initial nodes for uncontrolled mode */\n initialNodes?: NetworkNode[];\n /** Initial edges for uncontrolled mode */\n initialEdges?: NetworkEdge[];\n /** Headless store injection */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n store?: any;\n /** Enable debug mode */\n debug?: boolean;\n /** Callback when a node is clicked or selection changes (null when deselected) */\n onNodeClick?: (node: NetworkNode | null) => void;\n /** Callback when an edge is clicked */\n onEdgeClick?: (edge: NetworkEdge) => void;\n /** Callback when device view changes */\n onViewChange?: (nodeId: string, view: DeviceView) => void;\n /** Callback when rack face changes */\n onRackFaceChange?: (rackId: string, face: DeviceView) => void;\n /** CSS class name */\n className?: string;\n /** Inline styles */\n style?: React.CSSProperties;\n /** If true, vertically align rack bottoms to the same baseline */\n alignRacksToBottom?: boolean;\n /** Color mode for the diagram */\n colorMode?: 'light' | 'dark' | 'system';\n /** Callback when React Flow instance is initialized */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onInit?: (instance: any) => void;\n /** Callback to get React Flow methods for save/restore */\n onFlowMethods?: (methods: { \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toObject: () => any; \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setViewport: (viewport: any) => void; \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setNodes: (nodes: any[]) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n setEdges: (edges: any[]) => void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n toImage: (options?: any) => Promise<string> \n }) => void;\n /** Show download button */\n showDownloadButton?: boolean;\n /** Download button position */\n downloadButtonPosition?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\n /** Custom download button text */\n downloadButtonText?: string;\n /** Download button styling options */\n downloadButtonStyle?: React.CSSProperties;\n /** Allow reconnecting existing edges from either end */\n allowReconnectExisting?: boolean;\n /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */\n useSmoothstepEdgesForTubes?: boolean;\n}\n\nexport * from './netbox';\n","/**\n * Power connector utilities for consistent styling across devices and PDUs\n */\n\nexport interface PowerConnectorConfig {\n type: 'C13' | 'C14' | 'C19' | 'C20';\n color: string;\n borderColor: string;\n amperage: number;\n voltage: number;\n phases: number;\n}\n\nexport const POWER_CONNECTORS: Record<string, PowerConnectorConfig> = {\n C13: {\n type: 'C13',\n color: '#f59e0b', // Orange\n borderColor: '#d97706',\n amperage: 10,\n voltage: 230,\n phases: 1\n },\n C14: {\n type: 'C14',\n color: '#f59e0b', // Orange\n borderColor: '#d97706',\n amperage: 10,\n voltage: 230,\n phases: 1\n },\n C19: {\n type: 'C19',\n color: '#fbbf24', // Amber\n borderColor: '#d97706',\n amperage: 16,\n voltage: 230,\n phases: 1\n },\n C20: {\n type: 'C20',\n color: '#fbbf24', // Amber\n borderColor: '#d97706',\n amperage: 16,\n voltage: 230,\n phases: 1\n }\n};\n\nexport interface PowerPortStyle {\n width: number;\n height: number;\n borderRadius?: string;\n clipPath?: string;\n color: string;\n borderColor: string;\n fontSize: string;\n}\n\n/**\n * Get consistent power port styling for any connector type\n */\nexport function getPowerPortStyle(connectorType: string): PowerPortStyle {\n const connector = POWER_CONNECTORS[connectorType];\n if (!connector) {\n throw new Error(`Unknown connector type: ${connectorType}`);\n }\n\n const isHighPower = connector.amperage === 16; // C19/C20 are 16A\n\n // Size: High power connectors are bigger\n const width = isHighPower ? 12 : 8; // C19/C20 bigger; C13/C14 smaller\n const height = isHighPower ? 10 : 5; // C19/C20 bigger; C13/C14 smaller\n\n // Shape: C13/C14 have chamfered corners, C19/C20 have rounded corners\n const cornerStyle = isHighPower \n ? { borderRadius: '3px' } // C19/C20: rounded corners\n : { \n clipPath: `polygon(2px 0, calc(100% - 2px) 0, 100% 2px, 100% 100%, 0 100%, 0 2px)`,\n borderRadius: '0px'\n };\n\n return {\n width,\n height,\n color: connector.color,\n borderColor: connector.borderColor,\n fontSize: isHighPower ? '3px' : '4px',\n ...cornerStyle\n };\n}\n\n/**\n * Get connector configuration by type\n */\nexport function getConnectorConfig(connectorType: string): PowerConnectorConfig {\n const connector = POWER_CONNECTORS[connectorType];\n if (!connector) {\n throw new Error(`Unknown connector type: ${connectorType}`);\n }\n return connector;\n}\n\n/**\n * Determine if a connector is high power (16A)\n */\nexport function isHighPowerConnector(connectorType: string): boolean {\n const connector = getConnectorConfig(connectorType);\n return connector.amperage === 16;\n}\n\n/**\n * Get PDU port type based on position in cycle\n * PDU cycle: [8xC13, 2xC19] = 10 ports per cycle\n */\nexport function getPDUPortType(portIndex: number): string {\n const cyclePosition = portIndex % 10; // 10 ports per cycle\n return cyclePosition < 8 ? 'C13' : 'C19';\n}\n\n/**\n * Get device connector type based on device name\n */\nexport function getDeviceConnectorType(deviceName: string): string {\n const name = deviceName.toLowerCase();\n \n // High power devices use C20\n if (name.includes('mx304') || name.includes('mx480') || name.includes('mx960')) {\n return 'C20';\n }\n \n // Standard devices use C14\n return 'C14';\n}\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode, Width, PortBlock, Port } from '../types';\nimport { U_HEIGHT_PX } from '../utils/constants';\nimport { getPowerPortStyle, getConnectorConfig, getDeviceConnectorType } from '../utils/power-connectors';\nimport { getStatusColor } from '../utils/status-colors';\n\n// Power connector styling is now handled by shared utility\n\nexport const DeviceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { \n label, \n status = 'active', \n deviceType = 'server',\n manufacturer,\n role,\n uHeight = 1,\n width = Width.FULL, // Default to full width\n ports = [], // Array of port configurations\n rearPorts = [],\n view // Optional view override\n } = data;\n\n // Determine view: prefer explicit view; if both front and rear ports exist, default to 'front'\n const currentFace = view || ((rearPorts.length > 0 && ports.length === 0) ? 'rear' : 'front');\n\n // Debug logging removed in production build; keep component silent by default\n\n // Create handle-to-side mapping for zIndex calculation\n const handleSideMap: Record<string, 'front' | 'rear'> = {};\n \n // Map ALL handles to their sides (both front and rear) for proper zIndex calculation\n // This should be independent of the current view - handles have fixed positions\n \n // Front view handles (always on front regardless of current view)\n handleSideMap['net-top'] = 'front';\n handleSideMap['net-bottom'] = 'front';\n // Add any custom front handles from ports array\n if (ports.length > 0) {\n ports.forEach(portBlock => {\n portBlock.ports.forEach(port => {\n const handleId = port.type?.includes('power') ? port.label : `${portBlock.name}-${port.label}`;\n handleSideMap[handleId] = 'front';\n });\n });\n }\n \n // Rear view handles (always on rear regardless of current view)\n handleSideMap['pwr-left-1'] = 'rear';\n handleSideMap['pwr-left-2'] = 'rear';\n handleSideMap['net-right-1'] = 'rear';\n handleSideMap['net-right-2'] = 'rear';\n // Add any custom rear handles from rearPorts array\n if (rearPorts.length > 0) {\n rearPorts.forEach(portBlock => {\n portBlock.ports.forEach(port => {\n const handleId = port.type?.includes('power') ? port.label : `${portBlock.name}-${port.label}`;\n handleSideMap[handleId] = 'rear';\n });\n });\n }\n \n\n // Removed data mutation; z-index is derived in headless selectors\n\n // Calculate device height based on U height\n const deviceHeight = uHeight * U_HEIGHT_PX;\n \n // Calculate rackDevice width based on width setting\n // Rack width is 300px, so full width = 300px, half width = 150px\n const rackDeviceWidth = width === Width.HALF ? '150px' : '304px';\n const rackDeviceLeft = width === Width.HALF ? '150px' : undefined;\n\n // Render ports from port arrays\n const renderPortsFromArray = (portBlocks: PortBlock[], position: 'front' | 'rear') => {\n const handles: React.ReactElement[] = [];\n \n if (portBlocks.length === 0) return handles;\n \n // Calculate port dimensions based on device height\n const portWidth = Math.max(4, Math.floor(deviceHeight * 0.4)); // 40% of device height, minimum 4px\n const portHeight = Math.max(2, Math.floor(deviceHeight * 0.2)); // 20% of device height, minimum 2px\n \n portBlocks.forEach((portBlock, _blockIndex) => {\n portBlock.ports.forEach((port: Port, portIndex: number) => {\n const isPower = !!port.type && port.type.includes('power');\n // Remove front-facing power connections: skip power ports on front face\n if (position === 'front' && isPower) {\n return;\n }\n const handleId = isPower ? `${port.label}` : `${portBlock.name}-${port.label}`;\n const isConnected = port.connected;\n \n // Determine port color based on type and cable medium\n let portColor = '#6b7280'; // Default grey for empty/disconnected\n if (isConnected) {\n if (port.type?.includes('power')) {\n portColor = port.type === 'power_c19' ? '#fbbf24' : '#f59e0b'; // Amber for C19, orange for C13\n } else if (port.type === 'console' || port.type === 'mgmt') {\n portColor = '#8b5cf6'; // Purple for management\n } else if (port.type === 'usb') {\n portColor = '#10b981'; // Green for USB\n } else {\n // Network port colors based on cable/transceiver type\n switch (port.cableType) {\n case 'smf': // Single Mode Fiber\n portColor = '#fbbf24'; // Yellow\n break;\n case 'cat6': // Category 6 Ethernet\n portColor = '#8b5cf6'; // Purple\n break;\n case 'om3': // OM3 Multimode Fiber\n portColor = '#06b6d4'; // Aqua/Cyan\n break;\n case 'om4': // OM4 Multimode Fiber\n portColor = '#8b5cf6'; // Violet\n break;\n case 'om5': // OM5 Multimode Fiber\n portColor = '#84cc16'; // Lime Green\n break;\n case 'cat5e': // Category 5e Ethernet\n portColor = '#3b82f6'; // Blue\n break;\n case 'cat6a': // Category 6A Ethernet\n portColor = '#ef4444'; // Red\n break;\n case 'cat7': // Category 7 Ethernet\n portColor = '#f97316'; // Orange\n break;\n case 'fiber': // Generic fiber\n portColor = '#3b82f6'; // Blue\n break;\n case 'ethernet': // Generic ethernet\n portColor = '#10b981'; // Green\n break;\n default:\n portColor = '#10b981'; // Default green for connected\n }\n }\n }\n \n // Determine position based on port type and face\n let handlePosition = Position.Top;\n let handleStyle: React.CSSProperties = {\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: isConnected ? portColor : '#6b7280',\n border: `1px solid ${isConnected ? portColor : '#374151'}`,\n borderRadius: '1px',\n cursor: 'pointer',\n };\n \n if (position === 'front') {\n // Front view: network ports on top/bottom\n if (portIndex % 2 === 0) {\n handlePosition = Position.Top;\n handleStyle.transform = 'translateY(50%)';\n handleStyle.left = `${(portIndex / 2) * (portWidth + 2)}px`;\n } else {\n handlePosition = Position.Bottom;\n handleStyle.transform = 'translateY(-50%)';\n handleStyle.left = `${((portIndex - 1) / 2) * (portWidth + 2)}px`;\n }\n } else {\n // Rear view: patch panels use same top/bottom layout as front\n // Normalize deviceType to handle both 'patch_panel' (JSON) and 'patch-panel' (code)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n if (normalizedDeviceType === 'patch-panel') {\n // Patch panel rear ports: same layout as front (top/bottom)\n if (portIndex % 2 === 0) {\n handlePosition = Position.Top;\n handleStyle.transform = 'translateY(50%)';\n handleStyle.left = `${(portIndex / 2) * (portWidth + 2)}px`;\n } else {\n handlePosition = Position.Bottom;\n handleStyle.transform = 'translateY(-50%)';\n handleStyle.left = `${((portIndex - 1) / 2) * (portWidth + 2)}px`;\n }\n } else if (port.type?.includes('power')) {\n // Power ports on left (for non-patch-panel devices)\n handlePosition = Position.Left;\n handleStyle.transform = 'translateX(50%)'; // Move inside device boundary\n // Better spacing for 1U devices - start at top and space appropriately\n const baseTop = deviceHeight <= 20 ? 10 : 20;\n const spacing = deviceHeight <= 20 ? 30 : 50;\n handleStyle.top = `${baseTop + (portIndex * spacing)}%`;\n \n // Use shared utility for consistent power port styling\n const connectorType = getDeviceConnectorType(label);\n const portStyle = getPowerPortStyle(connectorType);\n \n handleStyle = {\n ...handleStyle,\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n };\n } else {\n // Network ports on right (for non-patch-panel devices)\n handlePosition = Position.Right;\n handleStyle.transform = 'translateX(-50%)';\n handleStyle.top = `${25 + (portIndex * 50)}%`;\n }\n }\n \n // Switches and routers output connections, so their network ports should be 'source'\n // But they also need 'target' handles for switch-to-switch mesh connections\n // Patch panels route traffic bidirectionally, so they need both source and target handles\n // Servers and other devices receive connections, so their network ports should be 'target'\n // Power ports are always 'target' (devices receive power)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n let handleType: 'source' | 'target';\n if (isPower) {\n handleType = 'target';\n } else if (deviceType === 'switch' || deviceType === 'router') {\n handleType = 'source'; // Switches/routers output network connections\n // Also create a target handle for switch-to-switch mesh connections\n handles.push(\n <Handle\n key={`${handleId}-target`}\n id={`${handleId}-target`}\n type=\"target\"\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} (input) ${isConnected ? '(connected)' : '(disconnected)'}`}\n />\n );\n } else if (isPatchPanel) {\n // Patch panels route traffic bidirectionally\n // Front ports: receive from switches (target), but also need source for routing to rear\n // Rear ports: send to other patch panels (source), but also receive from other patch panels (target)\n handleType = position === 'rear' ? 'source' : 'target';\n // Always create both source and target handles for patch panels to enable routing\n const oppositeType = position === 'rear' ? 'target' : 'source';\n handles.push(\n <Handle\n key={`${handleId}-${oppositeType}`}\n id={`${handleId}-${oppositeType}`}\n type={oppositeType}\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} (${oppositeType}) ${isConnected ? '(connected)' : '(disconnected)'}`}\n />\n );\n } else {\n handleType = isConnected ? 'source' : 'target'; // Other devices receive connections by default\n }\n\n handles.push(\n <Handle\n key={handleId}\n id={handleId}\n type={handleType}\n position={handlePosition}\n style={handleStyle}\n title={`${portBlock.name} - ${port.label} ${isConnected ? '(connected)' : '(disconnected)'}`}\n >\n {isPower ? portIndex + 1 : undefined}\n </Handle>\n );\n });\n });\n \n return handles;\n };\n\n // Render handles based on face orientation\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n \n // Calculate port dimensions based on device height\n const portWidth = Math.max(4, Math.floor(deviceHeight * 0.4)); // 40% of device height, minimum 4px\n const portHeight = Math.max(2, Math.floor(deviceHeight * 0.2)); // 20% of device height, minimum 2px\n \n if (currentFace === 'front') {\n // Front view\n // Front view: render from ports array if provided, else fall back to defaults\n if (ports.length > 0) {\n // Render ports from provided configuration\n return renderPortsFromArray(ports, 'front');\n }\n\n // Check if this is an AGG/core switch\n const isAGGSwitch = deviceType === 'switch' && (label.toLowerCase().includes('agg') || label.toLowerCase().includes('core') || role === 'agg' || role === 'core');\n if (isAGGSwitch) {\n return renderAGGSwitchHandles();\n }\n\n // Standard network ports on top and bottom (target - receives network from switches)\n // Standard device fallbacks\n handles.push(\n <Handle\n key=\"net-top\"\n id=\"net-top\"\n type=\"target\"\n position={Position.Top}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateY(50%)',\n }}\n title=\"Network Port (Top)\"\n />\n );\n\n handles.push(\n <Handle\n key=\"net-bottom\"\n id=\"net-bottom\"\n type=\"target\"\n position={Position.Bottom}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateY(-50%)',\n }}\n title=\"Network Port (Bottom)\"\n />\n );\n \n } else if (currentFace === 'rear') {\n // Rear view\n // Rear view: render from rearPorts array if provided, else fall back to defaults\n if (rearPorts.length > 0) {\n // Render ports from provided configuration\n return renderPortsFromArray(rearPorts, 'rear');\n }\n\n const isSwitch = deviceType === 'switch';\n // Normalize deviceType to handle both 'patch_panel' (JSON) and 'patch-panel' (code)\n const normalizedDeviceType = deviceType?.toLowerCase().replace(/_/g, '-') || '';\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n\n // Power ports on left side (all devices except patch panels)\n if (!isPatchPanel) {\n // Get connector type and styling using shared utility\n const connectorType = getDeviceConnectorType(label);\n const connector = getConnectorConfig(connectorType);\n const portStyle = getPowerPortStyle(connectorType);\n\n // Power port 1 - position based on device height\n const port1Top = deviceHeight <= 20 ? '10%' : '25%'; // Start at top for 1U devices\n \n handles.push(\n <Handle\n key=\"pwr-1\"\n id=\"pwr-left-1\"\n type=\"target\"\n position={Position.Left}\n style={{\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n transform: 'translateX(50%)', // Move inside the device boundary\n top: port1Top,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port 1 (${connector.type}) - ${connector.voltage}V, ${connector.amperage}A`}\n >\n 1\n </Handle>\n );\n\n // Power port 2 - position based on device height with proper spacing\n const port2Top = deviceHeight <= 20 ? '50%' : '75%'; // Position second port lower for 1U devices\n \n handles.push(\n <Handle\n key=\"pwr-2\"\n id=\"pwr-left-2\"\n type=\"target\"\n position={Position.Left}\n style={{\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n transform: 'translateX(50%)', // Move inside the device boundary\n top: port2Top,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port 2 (${connector.type}) - ${connector.voltage}V, ${connector.amperage}A`}\n >\n 2\n </Handle>\n );\n }\n\n // Network ports on right side (for non-switch, non-patch-panel devices)\n if (!isSwitch && !isPatchPanel) {\n handles.push(\n <Handle\n key=\"net-right-1\"\n id=\"net-right-1\"\n type=\"target\"\n position={Position.Right}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateX(-50%)',\n top: '25%',\n }}\n title=\"Network Port 1 (Right)\"\n />\n );\n\n handles.push(\n <Handle\n key=\"net-right-2\"\n id=\"net-right-2\"\n type=\"target\"\n position={Position.Right}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '0.5px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n transform: 'translateX(-50%)',\n top: '75%',\n }}\n title=\"Network Port 2 (Right)\"\n />\n );\n }\n }\n\n return handles;\n };\n\n // Render AGG switch handles: 48 ports on front, 4 uplinks on right\n const renderAGGSwitchHandles = () => {\n // AGG/core switch ports and uplinks\n const handles: React.ReactElement[] = [];\n \n // Calculate port dimensions - middle size for good visibility\n const portWidth = Math.max(10, Math.floor(deviceHeight * 0.45)); // 45% of device height, minimum 10px\n const portHeight = Math.max(5, Math.floor(deviceHeight * 0.25)); // 25% of device height, minimum 5px\n \n // 32 ports arranged in grid pattern: 16 on top, 16 on bottom\n // Create 32 front ports\n \n // Top row: 16 ports\n for (let i = 1; i <= 16; i++) {\n const handle = (\n <Handle\n key={`port-${i}`}\n id={`port-${i}`}\n type=\"source\"\n position={Position.Top}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '1px solid #059669', // Thinner border for cleaner look\n borderRadius: '2px',\n cursor: 'pointer',\n transform: 'translateY(50%)', // Pull handle into node\n zIndex: 1000,\n // Position ports across the top edge\n left: `${(i - 1) * (portWidth + 2)}px`, // Space ports across the width\n }}\n title={`Port ${i}`}\n />\n );\n \n \n \n handles.push(handle);\n }\n \n // Bottom row: 16 ports\n for (let i = 17; i <= 32; i++) {\n const bottomIndex = i - 16; // 1-16 for bottom row positioning\n const handle = (\n <Handle\n key={`port-${i}`}\n id={`port-${i}`}\n type=\"source\"\n position={Position.Bottom}\n style={{\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n background: '#10b981',\n border: '1px solid #059669', // Thinner border for cleaner look\n borderRadius: '2px',\n cursor: 'pointer',\n transform: 'translateY(-50%)', // Pull handle into node\n zIndex: 1000,\n // Position ports across the bottom edge\n left: `${(bottomIndex - 1) * (portWidth + 2)}px`, // Space ports across the width\n }}\n title={`Port ${i}`}\n />\n );\n \n \n \n handles.push(handle);\n }\n \n // 4 uplink ports on the right edge (larger, different color)\n for (let i = 1; i <= 4; i++) {\n const uplinkWidth = Math.max(4, Math.floor(deviceHeight * 0.3)); // Larger uplink ports\n const uplinkHeight = Math.max(3, Math.floor(deviceHeight * 0.15)); // Taller uplink ports\n \n handles.push(\n <Handle\n key={`uplink-${i}`}\n id={`uplink-${i}`}\n type=\"source\"\n position={Position.Right}\n style={{\n width: `${uplinkWidth}px`,\n height: `${uplinkHeight}px`,\n background: '#8b5cf6', // Purple color for uplinks\n border: '0.5px solid #7c3aed',\n borderRadius: '0.5px',\n cursor: 'pointer',\n transform: 'translateX(-50%)', // Pull handle into node\n }}\n title={`Uplink ${i}`}\n />\n );\n }\n\n return handles;\n };\n\n return (\n <div\n className={`device-node ${selected ? 'selected' : ''}`}\n style={{\n background: '#1f2937',\n border: `1px solid ${getStatusColor(status)}`,\n borderRadius: '2px',\n padding: '0px', // Remove padding to fix alignment\n width: rackDeviceWidth, // Width based on width setting\n ...(rackDeviceLeft && { left: rackDeviceLeft }), // Only set left for HALF width rackDevices\n height: `${deviceHeight}px`, // Exact U height (20px per U)\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '8px',\n boxShadow: selected ? '0 0 0 1px #3b82f6' : '0 1px 2px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n cursor: 'grab',\n marginBottom: '0px', // No gap - devices should be exactly U height\n boxSizing: 'border-box',\n marginTop: '0px',\n marginLeft: '0px',\n marginRight: '0px',\n }}\n >\n {/* Standard handles are now always rendered */}\n \n {/* U Position will be calculated dynamically based on position */}\n \n \n <div style={{ \n textAlign: 'center', \n flex: 1, \n display: 'flex', \n flexDirection: 'column', \n justifyContent: 'center',\n overflow: 'hidden',\n padding: '2px', // Add small padding for text readability\n }}>\n <div style={{ \n fontWeight: 'bold', \n fontSize: '7px',\n lineHeight: '1.1',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}>\n {label}\n </div>\n {uHeight > 1 && (\n <div style={{ \n fontSize: '6px', \n color: '#9ca3af',\n lineHeight: '1',\n }}>\n {manufacturer}\n </div>\n )}\n </div>\n \n {/* U Height indicator */}\n {uHeight > 1 && (\n <div\n style={{\n position: 'absolute',\n bottom: '1px',\n right: '1px',\n background: '#374151',\n color: '#9ca3af',\n padding: '1px 2px',\n borderRadius: '1px',\n fontSize: '6px',\n lineHeight: '1',\n }}\n >\n {uHeight}U\n </div>\n )}\n \n {/* Status indicator */}\n <div\n style={{\n position: 'absolute',\n bottom: '1px',\n left: '1px',\n width: '4px',\n height: '4px',\n background: getStatusColor(status),\n borderRadius: '50%',\n }}\n />\n \n {/* React Flow edge handles based on face orientation */}\n {renderHandles()}\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\nimport { getPowerPortStyle, getPDUPortType } from '../utils/power-connectors';\n\nexport enum MgmtUnitPosition {\n TOP = 'top',\n MIDDLE = 'middle',\n BOTTOM = 'bottom'\n}\n\nexport const VerticalPDU: React.FC<NodeProps<NetworkNode['data']>> = ({\n data,\n selected,\n}) => {\n const {\n label,\n status = 'active',\n heightCm = 100,\n powerPorts = 36, // Default number of AC power ports (10 C13 + 2 C19) × 3\n widthPx = 15,\n mgmt_unit, // Optional management unit position\n } = data;\n\n // Convert cm to pixels (1cm = 4.2px)\n const heightPx = heightCm * 4.2;\n\n // Completely custom vertical positioning for C13/C19/sets\n const renderPowerHandles = () => {\n // CYCLE = [8xC13, 2xC19], three times (for 30 ports)\n // Strategy:\n // - Use minimal/gapless \"start\" offset (header), so first port right beneath header.\n // - C13 ports: minimal gap (tight)\n // - C19 ports: even tighter gap than C13 (or zero)\n // - After last C19 of set: add a MUCH bigger gap before the new cycle (visual break).\n // - Ensure total height, including all ports and gaps, fits exactly into the available drawing area, and cycles are visually distinct.\n const cycleLength = 10; // 8 C13, 2 C19\n const nCycles = Math.ceil(powerPorts / cycleLength);\n const portsPerCycle = Array(cycleLength).fill(0).map((_, i) => (i < 8 ? '10A' : '16A'));\n\n // Sizing\n const C13_HEIGHT = 5;\n const C19_HEIGHT = 7;\n\n // Build metadata of port types and port heights\n const portMeta = [];\n for (let c = 0, idx = 0; c < nCycles; ++c) {\n for (let i = 0; i < cycleLength && idx < powerPorts; ++i, ++idx) {\n const portType = portsPerCycle[i];\n const is16A = portType === '16A';\n portMeta.push({\n portType,\n is16A,\n idx,\n isLastInCycle: i === cycleLength - 1,\n // For gap calculation\n isC19: is16A,\n portHeight: is16A ? C19_HEIGHT : C13_HEIGHT,\n });\n }\n }\n\n // Calculate the \"cycle\" indices (where to add the larger cycle gap)\n const handles = [];\n // Account for header height (20px) and add minimal padding\n const headerHeight = 15;\n const availableHeight = heightPx - headerHeight - 3; // 5px padding at bottom\n\n // REDUCE vertical spacing: 30% less spacing between ports\n // So multiply the calculated spacing by 0.7\n const rawPortSpacing = availableHeight / (powerPorts - 9);\n const portSpacing = rawPortSpacing * 0.5; // Even tighter spacing\n \n for (let i = 0; i < powerPorts; i++) {\n const yPos = headerHeight - 2 + (portSpacing * i); // Start slightly above header\n const handleId = `${i + 1}`;\n \n // Check if this position should be the management unit\n const isMgmtPosition = mgmt_unit && (\n (mgmt_unit === 'top' && i === 0) ||\n (mgmt_unit === 'middle' && i === Math.floor(powerPorts / 2)) ||\n (mgmt_unit === 'bottom' && i === powerPorts - 1)\n );\n \n if (isMgmtPosition) {\n handles.push(renderMgmtUnit(yPos));\n continue;\n }\n \n // Get port type and styling using shared utility\n const portType = getPDUPortType(i);\n const portStyle = getPowerPortStyle(portType);\n \n // Fix: Center the port more accurately (add -1px shift for visual center).\n const leftPx = Math.round((widthPx - portStyle.width) / 2 -1) ;\n\n handles.push(\n <Handle\n key={`handle-${handleId}`}\n type=\"source\"\n position={Position.Right}\n id={handleId}\n style={{\n position: 'absolute',\n left: `${leftPx}px`,\n top: `${yPos - (portStyle.height / 2)}px`,\n width: `${portStyle.width}px`,\n height: `${portStyle.height}px`,\n background: portStyle.color,\n border: `1px solid ${portStyle.borderColor}`,\n cursor: 'pointer',\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: portStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: portStyle.borderRadius,\n clipPath: portStyle.clipPath,\n }}\n title={`Power Port ${i + 1} (${portType})`}\n >\n {i + 1}\n </Handle>\n );\n }\n return handles;\n };\n\n // Render management unit as a power port in the sequence\n const renderMgmtUnit = (yPos: number) => {\n const mgmtWidth = 16;\n const mgmtHeight = 12;\n\n return (\n <div\n key=\"mgmt-unit\"\n style={{\n position: 'absolute',\n left: `${(widthPx - mgmtWidth) / 2}px`,\n top: `${yPos - (mgmtHeight / 2)}px`,\n width: `${mgmtWidth}px`,\n height: `${mgmtHeight}px`,\n background: '#1a1a1a',\n border: '1px solid #374151',\n borderRadius: '1px',\n display: 'flex',\n flexDirection: 'column',\n padding: '1px',\n zIndex: 10,\n }}\n >\n {/* Screen positioned on the left */}\n <div\n style={{\n position: 'absolute',\n left: '-10px',\n top: '1px',\n background: '#ffffff',\n border: '0.5px solid #6b7280',\n borderRadius: '0.5px',\n width: '8px',\n height: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '3px',\n color: '#10b981',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n transform: 'rotate(90deg)',\n transformOrigin: 'center',\n }}\n >\n APC\n </div>\n \n {/* Single Network Port Handle */}\n <Handle\n key=\"mgmt-net-1\"\n type=\"source\"\n position={Position.Right}\n id=\"mgmt-net-1\"\n style={{\n width: '70%',\n height: '6px',\n background: '#10b981',\n border: '1px solid #059669',\n borderRadius: '1px',\n cursor: 'pointer',\n zIndex: 11,\n margin: '0 auto',\n }}\n title=\"Management Network Port\"\n />\n </div>\n );\n };\n\n return (\n <div\n className={`vertical-pdu-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'linear-gradient(90deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n border: `1px solid ${getStatusColor(status)}`,\n borderRadius: '2px',\n padding: 0,\n width: `${widthPx}px`,\n height: `${heightPx}px`,\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 1px 3px rgba(0,0,0,0.3)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n \n {/* PDU Header */}\n <div style={{ \n textAlign: 'center', \n marginBottom: 0, \n zIndex: 2, \n background: 'linear-gradient(90deg, #4a5568 0%, #2d3748 50%, #4a5568 100%)', \n padding: '2px',\n position: 'relative',\n height: '20px',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n borderBottom: '1px solid #4a5568',\n }}>\n <div style={{ fontWeight: 'bold', fontSize: '6px', color: '#e2e8f0' }}>{label}</div>\n </div>\n \n {/* PDU Body with power ports */}\n <div\n style={{\n flex: 1,\n background: 'linear-gradient(180deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n position: 'relative',\n minHeight: `${heightPx - 20}px`,\n overflow: 'hidden',\n }}\n >\n {renderPowerHandles()}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps, useEdges, Edge } from 'reactflow';\nimport { NetworkNode, NetworkEdge } from '../types';\n\nexport const SpliceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { lossDb } = data || {};\n // Use useEdges hook to subscribe to edge changes - this will cause re-render when edges change\n const edges = useEdges<NetworkEdge>();\n \n // Get colors from connected edges, not from node data\n // Left handle can receive connections (target)\n const leftEdge = edges.find((e: Edge<NetworkEdge>) => e.target === id && e.targetHandle === 'left') as NetworkEdge | undefined;\n // Right handle can both send (source) and receive (target) connections\n const rightEdgeAsSource = edges.find((e: Edge<NetworkEdge>) => e.source === id && e.sourceHandle === 'right') as NetworkEdge | undefined;\n const rightEdgeAsTarget = edges.find((e: Edge<NetworkEdge>) => e.target === id && e.targetHandle === 'right') as NetworkEdge | undefined;\n const rightEdge = rightEdgeAsSource || rightEdgeAsTarget;\n \n // Get color from edge data, or use default gray if no edge\n const leftColor = leftEdge?.data?.color || '#555';\n const rightColor = rightEdge?.data?.color || '#555';\n \n // Only show glow when both handles are connected\n const bothConnected = !!leftEdge && !!rightEdge;\n\n return (\n <div\n className={`splice-node ${selected ? 'selected' : ''}`}\n style={{\n width: 69,\n height: 16,\n borderRadius: 8,\n border: 'none',\n outline: 'none',\n position: 'relative',\n background: 'transparent',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : 'none',\n }}\n >\n {/* Split background showing both colors with opacity for text readability */}\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n borderRadius: 8,\n overflow: 'hidden',\n opacity: 0.75,\n pointerEvents: 'none', // Don't block handles\n }}\n >\n <div style={{ background: leftColor }} />\n <div style={{ background: rightColor }} />\n </div>\n \n {/* Overlay with blur and opacity to make text clearer - respects dark/light mode */}\n <div\n className=\"splice-text-overlay\"\n style={{\n position: 'absolute',\n inset: 0,\n borderRadius: 8,\n pointerEvents: 'none',\n zIndex: 1,\n }}\n />\n \n {/* Thin glow line at the weld junction - only when both handles are connected */}\n {bothConnected && (\n <div\n className=\"splice-glow\"\n style={{\n position: 'absolute',\n left: '50%',\n top: 0,\n bottom: 0,\n width: '1px',\n background: 'rgba(255, 255, 255, 0.6)',\n boxShadow: '0 0 2px rgba(255, 255, 255, 0.8), 0 0 4px rgba(255, 255, 255, 0.4)',\n pointerEvents: 'none',\n zIndex: 2,\n }}\n />\n )}\n \n {/* Loss value label - only show when both handles are connected */}\n {bothConnected && typeof lossDb === 'number' && (\n <div\n className=\"splice-text-label animate-in\"\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 9,\n fontFamily: 'monospace',\n pointerEvents: 'none',\n zIndex: 3,\n fontWeight: 'bold',\n }}\n >\n {`${lossDb.toFixed(2)} dB`}\n </div>\n )}\n \n {/* Left handle (target) - receives connections - only one connection allowed */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"left\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: leftColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n left: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n \n {/* Right handle (source) - sends connections - only one connection allowed */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"right\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: rightColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n right: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n \n {/* Right handle (target) - receives connections - only one connection allowed */}\n <Handle\n type=\"target\"\n position={Position.Right}\n id=\"right\"\n isConnectable={true}\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n border: 'none',\n background: rightColor || '#555',\n zIndex: 100,\n cursor: 'crosshair',\n right: -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n </div>\n );\n};\n","import { NetworkNode } from '../types';\n\n/**\n * Height of each holder position in pixels (one splice per holder)\n */\nexport const HOLDER_HEIGHT_PX = 20;\n\n/**\n * Tray header height in pixels (smaller than rack header for compact trays)\n */\nexport const TRAY_HEADER_HEIGHT = 32;\n\n/**\n * Bottom padding for tray in pixels\n */\nexport const TRAY_BOTTOM_PADDING = 4;\n\n/**\n * Number of holders per tray (12f per tray)\n */\nexport const HOLDERS_PER_TRAY = 12;\n\n/**\n * Splice width in pixels (must match SpliceNode width)\n */\nexport const SPLICE_WIDTH_PX = 69;\n\n/**\n * Tray width in pixels (narrower to fit splice properly)\n */\nexport const TRAY_WIDTH_PX = 80;\n\n/**\n * Fixed X position to center splices within tray content\n */\nexport const SPLICE_CENTER_X = (TRAY_WIDTH_PX - SPLICE_WIDTH_PX) / 2;\n\n/**\n * Calculate holder position from Y coordinate within a tray\n */\nexport const calculateHolderPositionFromY = (\n tray: NetworkNode,\n y: number\n): number => {\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = y - startY;\n const holderPosition = Math.round(relativeY / HOLDER_HEIGHT_PX) + 1;\n const maxHolders = HOLDERS_PER_TRAY;\n return Math.max(1, Math.min(maxHolders, holderPosition));\n};\n\n/**\n * Snap a splice to the nearest holder position within a tray\n */\nexport const snapToSplicePosition = (\n splice: NetworkNode,\n tray: NetworkNode,\n newPosition: { x: number; y: number },\n allNodes: NetworkNode[]\n): { x: number; y: number; holderPosition?: number } => {\n if (!splice.parentId || splice.parentId !== tray.id) {\n return newPosition;\n }\n\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = newPosition.y - startY;\n const calculatedPosition = Math.round(relativeY / HOLDER_HEIGHT_PX) + 1;\n const maxPosition = HOLDERS_PER_TRAY;\n const snappedPosition = Math.max(1, Math.min(maxPosition, calculatedPosition));\n\n // Check if position is available\n if (!isHolderPositionAvailable(tray, splice, snappedPosition, allNodes)) {\n const availablePosition = findNextAvailableHolderPosition(tray, splice, allNodes, snappedPosition);\n if (availablePosition !== snappedPosition) {\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: startY + (availablePosition - 1) * HOLDER_HEIGHT_PX + baseOffset,\n holderPosition: availablePosition,\n };\n }\n }\n\n // Snap to exact holder position, left aligned x\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n const snappedY = startY + (snappedPosition - 1) * HOLDER_HEIGHT_PX + baseOffset;\n\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: snappedY,\n holderPosition: snappedPosition,\n };\n};\n\n/**\n * Check if a holder position is available in a tray\n */\nexport const isHolderPositionAvailable = (\n tray: NetworkNode,\n splice: NetworkNode,\n position: number,\n allNodes: NetworkNode[]\n): boolean => {\n const trayChildren = allNodes.filter(\n (n) => n.parentId === tray.id && n.type === 'splice' && n.id !== splice.id\n );\n\n return !trayChildren.some((child) => {\n const childPosition = (child.data as NetworkNode['data']).holderPosition;\n return childPosition === position;\n });\n};\n\n/**\n * Find the next available holder position\n */\nexport const findNextAvailableHolderPosition = (\n tray: NetworkNode,\n splice: NetworkNode,\n allNodes: NetworkNode[],\n startFrom: number = 1\n): number => {\n for (let pos = startFrom; pos <= HOLDERS_PER_TRAY; pos++) {\n if (isHolderPositionAvailable(tray, splice, pos, allNodes)) {\n return pos;\n }\n }\n\n // Try positions before startFrom\n for (let pos = startFrom - 1; pos >= 1; pos--) {\n if (isHolderPositionAvailable(tray, splice, pos, allNodes)) {\n return pos;\n }\n }\n\n return 1; // Fallback to position 1\n};\n\n/**\n * Calculate splice position based on holder number within a tray\n */\nexport const calculateSplicePositionFromNumber = (\n tray: NetworkNode,\n holderPosition: number\n): { x: number; y: number } => {\n const startY = TRAY_HEADER_HEIGHT;\n // Position splice in holder slot (HOLDER_HEIGHT_PX = 20, splice height = 16)\n // All splices moved down by 3px (2px original + 3px = 5px)\n const baseOffset = 5;\n const spliceY = startY + (holderPosition - 1) * HOLDER_HEIGHT_PX + baseOffset;\n\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: spliceY,\n };\n};\n","import React, { useState } from 'react';\nimport { NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { TRAY_HEADER_HEIGHT, HOLDER_HEIGHT_PX, HOLDERS_PER_TRAY, TRAY_WIDTH_PX, TRAY_BOTTOM_PADDING } from '../utils/splice-positioning';\n\nexport const SpliceTrayNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const { label = 'Splice Tray' } = data || {};\n const [showHolderMarkers, setShowHolderMarkers] = useState(false);\n\n // Generate holder position markers (like U markers in racks)\n const renderHolderPositions = () => {\n if (!showHolderMarkers) return null;\n const positions = [];\n const startY = TRAY_HEADER_HEIGHT;\n\n for (let i = 1; i <= HOLDERS_PER_TRAY; i++) {\n const yPos = startY + (i - 1) * HOLDER_HEIGHT_PX;\n\n positions.push(\n <div\n key={i}\n style={{\n position: 'absolute',\n left: '-35px',\n top: `${yPos}px`,\n background: '#374151',\n color: '#9ca3af',\n padding: '2px 4px',\n borderRadius: '2px',\n fontSize: '8px',\n fontWeight: 'bold',\n width: '28px',\n textAlign: 'center',\n border: '1px solid #4b5563',\n zIndex: 10,\n height: `${HOLDER_HEIGHT_PX}px`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n >\n H{i}\n </div>\n );\n }\n return positions;\n };\n\n return (\n <div\n className={`splice-tray-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'transparent',\n border: 'none',\n borderRadius: '8px',\n padding: 0,\n width: `${TRAY_WIDTH_PX}px`, // Width to accommodate splice\n height: `${TRAY_HEADER_HEIGHT + HOLDERS_PER_TRAY * HOLDER_HEIGHT_PX + TRAY_BOTTOM_PADDING}px`, // Header + holder area + bottom padding\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected\n ? '0 0 0 2px #3b82f6'\n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* Tray Header */}\n <div\n style={{\n textAlign: 'center',\n marginBottom: 0,\n zIndex: 2,\n background: '#1f2937',\n padding: '2px',\n position: 'relative',\n height: `${TRAY_HEADER_HEIGHT}px`,\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '6px',\n borderRadius: '8px',\n }}\n >\n <div style={{ fontWeight: 'bold', fontSize: '10px' }}>{label}</div>\n <button\n onPointerDown={(e) => {\n e.stopPropagation();\n }}\n onMouseDown={(e) => {\n e.stopPropagation();\n }}\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n setShowHolderMarkers(!showHolderMarkers);\n }}\n style={{\n background: showHolderMarkers ? '#10b981' : '#374151',\n color: showHolderMarkers ? '#ffffff' : '#9ca3af',\n border: '1px solid #4b5563',\n borderRadius: '2px',\n padding: '2px 6px',\n fontSize: '8px',\n cursor: 'pointer',\n fontFamily: 'monospace',\n }}\n title={`${showHolderMarkers ? 'Hide' : 'Show'} holder markers`}\n >\n H\n </button>\n </div>\n\n {/* Holder position markers */}\n {renderHolderPositions()}\n\n {/* Content area where SpliceNode children will be placed */}\n <div\n style={{\n position: 'absolute',\n top: TRAY_HEADER_HEIGHT,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n }}\n />\n </div>\n );\n};\n","import React from 'react';\n\n/**\n * TIA-598-C standard fiber optic color codes (12 base colors)\n * Colors 1-12: Blue, Orange, Green, Brown, Slate, White, Red, Black, Yellow, Violet, Rose, Aqua\n * @public\n */\nexport const FIBER_COLORS_12 = [\n '#1f77b4', /* Blue */\n '#ff7f0e', /* Orange */\n '#2ca02c', /* Green */\n '#8c564b', /* Brown */\n '#708090', /* Slate */\n '#ffffff', /* White */\n '#d62728', /* Red */\n '#000000', /* Black */\n '#ffdf00', /* Yellow */\n '#8a2be2', /* Violet */\n '#ff69b4', /* Rose */\n '#00ffff' /* Aqua */\n] as const;\n\n/**\n * Fiber color ID type (1-24)\n * @public\n */\nexport type FiberColorId = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24;\n\n/**\n * Get the base color for a fiber color ID\n * Colors 13-24 use the same base colors as 1-12\n * @param id - Fiber color ID (1-24)\n * @returns Hex color code\n * @public\n */\nexport function baseColorFor(id: FiberColorId | number): string {\n const normalizedId = ((id - 1) % 12);\n return FIBER_COLORS_12[normalizedId];\n}\n\n/**\n * Check if a fiber color ID uses a striped pattern (13-24)\n * @param id - Fiber color ID (1-24)\n * @returns True if the color should be striped\n * @public\n */\nexport function isStriped(id: FiberColorId | number): boolean {\n return id > 12;\n}\n\n/**\n * Get CSS properties for a fiber color (solid or striped)\n * Colors 13-24 use a black stripe pattern over the base color\n * @param id - Fiber color ID (1-24)\n * @returns CSS properties for the color\n * @public\n */\nexport function fiberSolidOrStriped(id: FiberColorId | number): React.CSSProperties {\n const base = baseColorFor(id);\n if (isStriped(id)) {\n return {\n background: base,\n backgroundImage: `repeating-linear-gradient(45deg, ${base} 0 6px, #000 6px 9px)`,\n };\n }\n return { background: base };\n}\n\n/**\n * Get the hex color code for a fiber color ID\n * @param id - Fiber color ID (1-24)\n * @returns Hex color code\n * @public\n */\nexport function getFiberColor(id: FiberColorId | number): string {\n return baseColorFor(id);\n}\n\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { fiberSolidOrStriped, baseColorFor } from '../utils/fiber-colors';\n\n/**\n * TubeNode\n * - Rectangular node representing a buffer tube (horizontal orientation, rotated 180 degrees)\n * - Renders 12 or 24 fiber handles on the top side with TIA-598 colors\n * - Tube border tinted by tube index color (1..12 cycling)\n * - startOn parameter controls handle positioning:\n * - 'left-center' (default): handles centered on top, tube handle on bottom\n * - 'left': handles on left side, tube handle on left\n * - 'right': handles on right side with reversed colors, tube handle on right\n */\nexport const TubeNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id: _id }) => {\n const { fibersPerTube = 12, tubeIndex = 1, startOn = 'left-center' } = data || {};\n\n // Calculate dimensions - rectangle that fits all fibers horizontally (rotated 90 degrees to be flat)\n const fibers = Math.max(1, Math.min(24, Number(fibersPerTube) || 12));\n const handleSize = 14; // Handle size\n const handleSpacing = 4;\n const padding = 1; // Reduced padding to make tube thinner\n const borderWidth = 2; // Thinner border\n // Height must accommodate: border (2px * 2) + padding (1px * 2) + handle (14px) = 20px\n const height = 20; // Thinner tube but still fits handles inside and centered\n const totalHandlesWidth = (fibers * handleSize) + ((fibers - 1) * handleSpacing);\n const width = Math.max(60, totalHandlesWidth + (padding * 2) + (borderWidth * 2));\n\n const tubeBorderColor = baseColorFor(((tubeIndex - 1) % 12) + 1);\n const tubeConnectionHandleId = `tube-${tubeIndex}`;\n const tubeConnectionHandleSize = 18; // Larger handle for easier grabbing\n const connectionHandleStyle: React.CSSProperties & { '--fiber-bg'?: string } = {\n width: tubeConnectionHandleSize,\n height: tubeConnectionHandleSize,\n borderRadius: '50%',\n opacity: 0.25, // Visible but subtle\n pointerEvents: 'auto',\n background: tubeBorderColor,\n backgroundColor: tubeBorderColor,\n border: `2px solid ${tubeBorderColor}`,\n '--fiber-bg': tubeBorderColor,\n };\n\n // Determine tube connection handle position based on startOn\n const getTubeConnectionPosition = () => {\n if (startOn === 'left') return Position.Left;\n if (startOn === 'right') return Position.Right;\n return Position.Bottom; // default 'left-center'\n };\n\n // Render handles based on startOn mode\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n const innerWidth = width - (borderWidth * 2) - (padding * 2);\n \n let startLeft: number;\n let handlePosition: Position;\n let reverseColors = false;\n \n if (startOn === 'left') {\n // Handles start from left (not centered), positioned on top\n startLeft = padding;\n handlePosition = Position.Top;\n } else if (startOn === 'right') {\n // Handles start from right, positioned on top, colors reversed\n startLeft = padding + innerWidth - totalHandlesWidth;\n handlePosition = Position.Top;\n reverseColors = true;\n } else {\n // Default 'left-center': handles centered on top\n startLeft = padding + (innerWidth - totalHandlesWidth) / 2;\n handlePosition = Position.Top;\n }\n \n for (let i = 0; i < fibers; i++) {\n // Calculate fiber index - reverse if startOn is 'right'\n const fiberIdx = reverseColors ? (fibers - i) : (i + 1);\n const fiberStyle = fiberSolidOrStriped(fiberIdx);\n const baseColor = baseColorFor(fiberIdx);\n \n // Position handles on top, horizontally arranged\n const left = startLeft + (i * (handleSize + handleSpacing));\n const top = padding;\n\n // Build handle style with fiber color\n const handleBackground = fiberStyle.backgroundImage \n ? fiberStyle.backgroundImage\n : baseColor;\n\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n left: `${left}px`,\n top: `${top}px`,\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n border: 'none',\n background: handleBackground,\n backgroundColor: baseColor,\n zIndex: 10,\n cursor: 'pointer',\n '--fiber-bg': baseColor,\n };\n \n // Set background image variable if there is one\n if (fiberStyle.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberStyle.backgroundImage;\n }\n\n const fiberHandleId = `fiber-${fiberIdx}`;\n\n handles.push(\n <React.Fragment key={`fiber-${fiberIdx}`}>\n {/* Target handle - only one connection allowed */}\n <Handle\n id={fiberHandleId}\n type=\"target\"\n position={handlePosition}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={fiberIdx}\n data-fiber-color={baseColor}\n />\n {/* Source handle (overlapped to allow connect from either side) - only one connection allowed */}\n <Handle\n id={fiberHandleId}\n type=\"source\"\n position={handlePosition}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={fiberIdx}\n data-fiber-color={baseColor}\n />\n </React.Fragment>\n );\n }\n \n return handles;\n };\n\n return (\n <div\n style={{\n width: width,\n height: height,\n borderRadius: 4,\n background: '#111827',\n border: `${borderWidth}px solid ${selected ? '#3b82f6' : tubeBorderColor}`,\n position: 'relative',\n boxShadow: selected ? `0 0 0 ${borderWidth}px #3b82f6` : '0 2px 4px rgba(0,0,0,0.2)',\n padding: padding,\n boxSizing: 'border-box',\n }}\n >\n {/* Render fiber handles */}\n {renderHandles()}\n {/* Hidden handle for cable-to-tube connections - position depends on startOn */}\n <Handle\n id={tubeConnectionHandleId}\n type=\"target\"\n position={getTubeConnectionPosition()}\n isConnectable={true}\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n />\n <Handle\n id={tubeConnectionHandleId}\n type=\"source\"\n position={getTubeConnectionPosition()}\n isConnectable={true}\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n />\n </div>\n );\n};\n\n\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { fiberSolidOrStriped, baseColorFor } from '../utils/fiber-colors';\n\n/**\n * CableNode\n * - Visually mirrors TubeNode but represents an entire cable\n * - Each colored handle corresponds to a tube within the cable\n * - Displays cable summary text (fiber count + cable identifier)\n */\nexport const CableNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const {\n tubeCount = 12,\n fibersPerTube = 12,\n fiberCount: providedFiberCount,\n cableId = 'CBL-002',\n label,\n tubeStartIndex: rawTubeStartIndex = 1,\n color, // Cable color prop - used for border and button handle\n } = data || {};\n\n const tubes = Math.max(1, Math.min(24, Number(tubeCount) || 12));\n const tubeStartIndex = Math.max(1, Number(rawTubeStartIndex) || 1);\n const handleSize = 8;\n const handleSpacing = 2;\n const padding = 6;\n const innerPaddingTop = padding + handleSize + 4;\n const height = 60;\n const width = Math.max(120, (tubes * (handleSize + handleSpacing)) + (padding * 2));\n const totalFibers = providedFiberCount ?? tubes * (Number(fibersPerTube) || 12);\n\n const primaryText = label ?? `${totalFibers}f Cable`;\n const secondaryText = cableId ? `Cable ID ${cableId}` : undefined;\n const firstTubeColor = baseColorFor(tubeStartIndex);\n \n // Use provided color or fall back to first tube color\n const cableColor = color || firstTubeColor;\n const borderColor = selected ? '#3b82f6' : cableColor;\n\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n\n for (let i = 0; i < tubes; i++) {\n const tubeIdx = tubeStartIndex + i;\n const tubeStyle = fiberSolidOrStriped(tubeIdx);\n const baseColor = baseColorFor(tubeIdx);\n\n const left = padding + (i * (handleSize + handleSpacing));\n const top = -(handleSize / 2);\n\n const handleBackground = tubeStyle.backgroundImage ? tubeStyle.backgroundImage : baseColor;\n\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n left: `${left}px`,\n top: `${top}px`,\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n border: 'none',\n background: handleBackground,\n backgroundColor: baseColor,\n zIndex: 10,\n cursor: 'pointer',\n '--fiber-bg': baseColor,\n };\n\n if (tubeStyle.backgroundImage) {\n handleStyle['--fiber-bg-image'] = tubeStyle.backgroundImage;\n }\n\n const tubeHandleId = `tube-${tubeIdx}`;\n\n handles.push(\n <React.Fragment key={`tube-${tubeIdx}`}>\n <Handle\n id={tubeHandleId}\n type=\"target\"\n position={Position.Top}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={tubeIdx}\n data-tube-idx={tubeIdx}\n data-tube-color={baseColor}\n />\n <Handle\n id={tubeHandleId}\n type=\"source\"\n position={Position.Top}\n className=\"tube-fiber-handle\"\n isConnectable={true}\n style={handleStyle}\n data-fiber-idx={tubeIdx}\n data-tube-idx={tubeIdx}\n data-tube-color={baseColor}\n />\n </React.Fragment>\n );\n }\n\n return handles;\n };\n\n // Button handle on edge for cable-to-cable connections (max 1 connection)\n const buttonHandleId = 'cable-button';\n const buttonHandleSize = 8; // Smaller handle\n const buttonHandleStyle: React.CSSProperties = {\n width: buttonHandleSize,\n height: buttonHandleSize,\n borderRadius: '50%',\n background: cableColor,\n backgroundColor: cableColor,\n border: `1px solid ${cableColor}`,\n cursor: 'pointer',\n zIndex: 10,\n };\n\n const borderWidth = 2;\n \n return (\n <div\n style={{\n width,\n height,\n borderRadius: 4,\n background: '#111827',\n border: `${borderWidth}px solid ${borderColor}`,\n position: 'relative',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.2)',\n padding: padding,\n paddingTop: innerPaddingTop,\n boxSizing: 'border-box',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n textAlign: 'center',\n gap: 2,\n }}\n >\n {renderHandles()}\n {/* Button handle on bottom edge */}\n <Handle\n id={buttonHandleId}\n type=\"source\"\n position={Position.Bottom}\n className=\"cable-button-handle\"\n isConnectable={true}\n style={buttonHandleStyle}\n data-handle-type=\"cable-button\"\n data-cable-color={cableColor}\n />\n <Handle\n id={buttonHandleId}\n type=\"target\"\n position={Position.Bottom}\n className=\"cable-button-handle\"\n isConnectable={true}\n style={buttonHandleStyle}\n data-handle-type=\"cable-button\"\n data-cable-color={cableColor}\n />\n <div style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>\n {primaryText}\n </div>\n {secondaryText && (\n <div style={{ fontSize: 10, opacity: 0.8 }}>\n {secondaryText}\n </div>\n )}\n </div>\n );\n};\n\n","import React from 'react';\nimport { Handle, Position, NodeProps, useEdges, Edge } from 'reactflow';\nimport { NetworkNode, NetworkEdge } from '../types';\n\nexport const CouplerNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { connector = 'LC', couplerFiberCount, label, portLabelsLeft, portLabelsRight } = data || {};\n const edges = useEdges<NetworkEdge>();\n \n // Calculate dimensions based on fiber count\n const normalizedFiberCount = typeof couplerFiberCount === 'number' && [1, 2, 4].includes(couplerFiberCount)\n ? couplerFiberCount\n : 2;\n const portCount = Math.max(1, Math.min(4, normalizedFiberCount));\n const handleSize = 7;\n const handleSpacing = 3;\n const padding = 3;\n const minWidth = 60;\n const minHeight = 30;\n \n // Calculate height based on number of ports\n const totalHandlesHeight = (portCount * handleSize) + ((portCount - 1) * handleSpacing);\n const height = Math.max(minHeight, totalHandlesHeight + (padding * 2));\n const width = Math.max(minWidth, 80);\n \n // Get colors from connected edges for each port\n const getPortColor = (side: 'left' | 'right', portIndex: number): string => {\n const handleId = `${side}-${portIndex + 1}`;\n const edge = edges.find((e: Edge<NetworkEdge>) => \n (e.source === id && e.sourceHandle === handleId) ||\n (e.target === id && e.targetHandle === handleId)\n ) as NetworkEdge | undefined;\n return edge?.data?.color || '#555';\n };\n \n // Render handles for one side\n const renderHandles = (side: 'left' | 'right') => {\n const handles: React.ReactElement[] = [];\n const position = side === 'left' ? Position.Left : Position.Right;\n const labels = side === 'left' ? portLabelsLeft : portLabelsRight;\n \n for (let i = 0; i < portCount; i++) {\n const portIndex = i + 1;\n const handleId = `${side}-${portIndex}`;\n const portColor = getPortColor(side, i);\n \n // Calculate vertical position - center the ports vertically\n const totalHeight = totalHandlesHeight;\n const startTop = padding + (height - totalHeight) / 2;\n const top = startTop + (i * (handleSize + handleSpacing));\n \n const handleStyle: React.CSSProperties = {\n position: 'absolute',\n left: side === 'left' ? -5 : undefined,\n right: side === 'right' ? -5 : undefined,\n top: `${top}px`,\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n border: 'none',\n background: portColor,\n zIndex: 100,\n cursor: 'crosshair',\n transform: 'translateY(-50%)',\n };\n \n handles.push(\n <React.Fragment key={handleId}>\n {/* Target handle - receives connections */}\n <Handle\n id={handleId}\n type=\"target\"\n position={position}\n isConnectable={true}\n style={handleStyle}\n />\n {/* Source handle - sends connections */}\n <Handle\n id={handleId}\n type=\"source\"\n position={position}\n isConnectable={true}\n style={handleStyle}\n />\n </React.Fragment>\n );\n \n // Add port label if provided\n if (labels && labels[i]) {\n handles.push(\n <div\n key={`${handleId}-label`}\n style={{\n position: 'absolute',\n left: side === 'left' ? -30 : undefined,\n right: side === 'right' ? -30 : undefined,\n top: `${top}px`,\n transform: 'translateY(-50%)',\n fontSize: '8px',\n color: '#9ca3af',\n fontFamily: 'monospace',\n pointerEvents: 'none',\n textAlign: side === 'left' ? 'right' : 'left',\n width: '25px',\n }}\n >\n {labels[i]}\n </div>\n );\n }\n }\n \n return handles;\n };\n \n const displayLabel = label || `${connector}-${portCount}f`;\n \n return (\n <div\n className={`coupler-node ${selected ? 'selected' : ''}`}\n style={{\n width,\n height,\n borderRadius: 4,\n border: `2px solid ${selected ? '#3b82f6' : '#4b5563'}`,\n background: '#1f2937',\n position: 'relative',\n boxShadow: selected ? '0 0 0 2px #3b82f6' : '0 2px 4px rgba(0,0,0,0.2)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#e5e7eb',\n fontFamily: 'monospace',\n fontSize: '10px',\n padding: `${padding}px`,\n boxSizing: 'border-box',\n }}\n >\n {/* Left side handles */}\n {renderHandles('left')}\n \n {/* Center label */}\n <div\n style={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n textAlign: 'center',\n pointerEvents: 'none',\n zIndex: 1,\n }}\n >\n <div style={{ fontWeight: 'bold', fontSize: '9px' }}>{displayLabel}</div>\n </div>\n \n {/* Right side handles */}\n {renderHandles('right')}\n </div>\n );\n};\n\n","import { NetworkNode } from '../types';\nimport { TRAY_WIDTH_PX } from './splice-positioning';\n\n/**\n * Panel header height in pixels\n */\nexport const PANEL_HEADER_HEIGHT = 32;\n\n/**\n * Coupler slot height in pixels\n */\nexport const COUPLER_SLOT_HEIGHT_PX = 30;\n\n/**\n * Default number of couplers per panel\n */\nexport const COUPLERS_PER_PANEL = 24;\n\n/**\n * Default coupler width in pixels\n */\nexport const COUPLER_WIDTH_PX = 80;\n\n/**\n * Default panel width in pixels\n */\nexport const PANEL_WIDTH_PX = 400;\n\n/**\n * Default panel height in pixels\n */\nexport const PANEL_HEIGHT_PX = 300;\n\n/**\n * Panel border width in pixels\n */\nexport const PANEL_BORDER_WIDTH = 2;\n\n/**\n * Panel padding in pixels\n */\nexport const PANEL_PADDING = 8;\n\n/**\n * Spacing between tubes and trays in patch panels (horizontal spacing)\n */\nexport const PANEL_TUBE_TRAY_SPACING = 120;\n\n/**\n * Calculate coupler dimensions based on node data\n */\nexport function getCouplerDimensions(node: NetworkNode): { width: number; height: number } {\n const { couplerFiberCount } = node.data || {};\n const normalizedFiberCount = typeof couplerFiberCount === 'number' && [1, 2, 4].includes(couplerFiberCount)\n ? couplerFiberCount\n : 2;\n const portCount = Math.max(1, Math.min(4, normalizedFiberCount));\n const handleSize = 7;\n const handleSpacing = 3;\n const padding = 3;\n const minWidth = 60;\n const minHeight = 30;\n \n const totalHandlesHeight = (portCount * handleSize) + ((portCount - 1) * handleSpacing);\n const height = Math.max(minHeight, totalHandlesHeight + (padding * 2));\n const width = Math.max(minWidth, 80);\n \n return { width, height };\n}\n\n/**\n * Calculate tube dimensions based on node data\n */\nexport function getTubeDimensions(node: NetworkNode): { width: number; height: number } {\n const { fibersPerTube = 12 } = node.data || {};\n const fibers = Math.max(1, Math.min(24, Number(fibersPerTube) || 12));\n const handleSize = 14;\n const handleSpacing = 4;\n const padding = 1;\n const borderWidth = 2;\n const height = 20;\n const totalHandlesWidth = (fibers * handleSize) + ((fibers - 1) * handleSpacing);\n const width = Math.max(60, totalHandlesWidth + (padding * 2) + (borderWidth * 2));\n \n return { width, height };\n}\n\n/**\n * Get tray dimensions\n */\nexport function getTrayDimensions(_node: NetworkNode): { width: number; height: number } {\n // Tray dimensions are fixed\n return {\n width: TRAY_WIDTH_PX,\n height: 0, // Height doesn't affect width calculation\n };\n}\n\n/**\n * Get node dimensions based on node type\n */\nfunction getNodeDimensions(node: NetworkNode): { width: number; height: number } {\n if (node.type === 'coupler') {\n return getCouplerDimensions(node);\n } else if (node.type === 'tube') {\n return getTubeDimensions(node);\n } else if (node.type === 'splice-tray') {\n return getTrayDimensions(node);\n }\n // Default fallback\n return { width: 80, height: 30 };\n}\n\n/**\n * Calculate panel width based on content\n */\nexport function getPanelWidth(panelNode: NetworkNode): number {\n return panelNode.data?.panelWidth || PANEL_WIDTH_PX;\n}\n\n/**\n * Calculate panel height based on content\n */\nexport function getPanelHeight(panelNode: NetworkNode): number {\n return panelNode.data?.panelHeight || PANEL_HEIGHT_PX;\n}\n\n/**\n * Get inner content width (panel width minus borders/padding)\n */\nexport function getInnerContentWidth(panelNode: NetworkNode): number {\n const width = getPanelWidth(panelNode);\n return width - (PANEL_BORDER_WIDTH * 2) - (PANEL_PADDING * 2);\n}\n\n/**\n * Calculate coupler right X position\n */\nexport function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number {\n const innerWidth = getInnerContentWidth(panelNode);\n return innerWidth - couplerWidth;\n}\n\n/**\n * Calculate slot position from Y coordinate\n */\nexport function calculateSlotPositionFromY(y: number, slotHeight: number = COUPLER_SLOT_HEIGHT_PX): number {\n return Math.floor(y / slotHeight) + 1;\n}\n\n/**\n * Calculate Y coordinate from slot position\n */\nexport function calculateYFromSlotPosition(slot: number, slotHeight: number = COUPLER_SLOT_HEIGHT_PX): number {\n return (slot - 1) * slotHeight;\n}\n\n/**\n * Snap coupler to nearest slot position\n */\nexport function snapToCouplerPosition(\n coupler: NetworkNode,\n panel: NetworkNode,\n position: { x: number; y: number }\n): { x: number; y: number; slotPosition?: number } {\n const slotHeight = COUPLER_SLOT_HEIGHT_PX;\n const slot = calculateSlotPositionFromY(position.y, slotHeight);\n const snappedY = calculateYFromSlotPosition(slot, slotHeight);\n \n return {\n x: position.x,\n y: snappedY,\n slotPosition: slot,\n };\n}\n\n/**\n * Calculate panel dimensions based on child nodes\n */\nexport function calculatePanelDimensions(\n panelNode: NetworkNode,\n childNodes: NetworkNode[]\n): { width: number; height: number } {\n if (childNodes.length === 0) {\n return {\n width: panelNode.data?.panelWidth || PANEL_WIDTH_PX,\n height: panelNode.data?.panelHeight || PANEL_HEIGHT_PX,\n };\n }\n \n // Check if this panel has tubes, trays, and couplers (patch panel layout)\n const hasTubes = childNodes.some(n => n.type === 'tube');\n const hasTrays = childNodes.some(n => n.type === 'splice-tray');\n const hasCouplers = childNodes.some(n => n.type === 'coupler');\n \n let width: number;\n const handleExtension = 5; // Handles extend 5px outside nodes\n \n if (hasTubes && hasTrays && hasCouplers) {\n // Patch panel with tubes, trays, and couplers\n // Layout: [padding] [tube] [spacing] [tray] [coupler] [handle extension]\n \n // Find the leftmost tube and rightmost coupler\n let tubeWidth = 0;\n let couplerWidth = 0;\n \n for (const child of childNodes) {\n if (child.type === 'tube') {\n const dims = getTubeDimensions(child);\n if (dims.width > tubeWidth) {\n tubeWidth = dims.width;\n }\n } else if (child.type === 'coupler') {\n const dims = getCouplerDimensions(child);\n if (dims.width > couplerWidth) {\n couplerWidth = dims.width;\n }\n }\n }\n \n // Calculate width: padding + tube + spacing + tray + coupler + handle extension\n width = PANEL_PADDING + tubeWidth + PANEL_TUBE_TRAY_SPACING + TRAY_WIDTH_PX + couplerWidth + handleExtension;\n } else {\n // Standard layout: calculate based on rightmost child\n let maxRight = 0;\n \n for (const child of childNodes) {\n const dims = getNodeDimensions(child);\n const childRight = (child.position?.x || 0) + dims.width;\n \n if (childRight > maxRight) {\n maxRight = childRight;\n }\n }\n \n // Add padding and handle extension space\n width = maxRight + PANEL_PADDING + handleExtension;\n }\n \n // Ensure width is at least the minimum or explicit width\n width = Math.max(\n panelNode.data?.panelWidth || PANEL_WIDTH_PX,\n width\n );\n \n // Calculate height based on bottommost child\n let maxBottom = PANEL_HEADER_HEIGHT;\n \n for (const child of childNodes) {\n const dims = getNodeDimensions(child);\n const childBottom = (child.position?.y || 0) + dims.height;\n \n if (childBottom > maxBottom) {\n maxBottom = childBottom;\n }\n }\n \n const height = Math.max(\n panelNode.data?.panelHeight || PANEL_HEIGHT_PX,\n maxBottom + PANEL_PADDING\n );\n \n return { width, height };\n}\n\n/**\n * Calculate spacing between couplers\n */\nexport function calculateCouplerSpacing(\n numCouplers: number,\n couplerHeight: number,\n availableHeight: number\n): number {\n if (numCouplers === 0) return 0;\n if (numCouplers === 1) return couplerHeight;\n \n const totalCouplerHeight = numCouplers * couplerHeight;\n const availableSpacing = availableHeight - totalCouplerHeight;\n const spacingBetweenCouplers = Math.max(5, availableSpacing / (numCouplers - 1));\n return couplerHeight + spacingBetweenCouplers;\n}\n\n/**\n * Calculate coupler slot spacing\n */\nexport function calculateCouplerSlotSpacing(\n numCouplers: number,\n couplerHeight: number,\n availableHeight: number\n): number {\n return calculateCouplerSpacing(numCouplers, couplerHeight, availableHeight);\n}\n\n/**\n * Spacing between tubes and trays in closures (horizontal spacing)\n */\nexport const CLOSURE_TUBE_TRAY_SPACING = 20;\n\n/**\n * Default closure width in pixels\n */\nexport const CLOSURE_WIDTH_PX = 400;\n\n/**\n * Default closure height in pixels\n */\nexport const CLOSURE_HEIGHT_PX = 300;\n\n/**\n * Calculate closure dimensions based on child nodes\n * Closure layout: [padding] [left tubes] [spacing] [trays] [spacing] [right tubes] [padding]\n */\nexport function calculateClosureDimensions(\n closureNode: NetworkNode,\n childNodes: NetworkNode[]\n): { width: number; height: number } {\n if (childNodes.length === 0) {\n return {\n width: closureNode.data?.closureWidth || closureNode.data?.panelWidth || CLOSURE_WIDTH_PX,\n height: closureNode.data?.closureHeight || closureNode.data?.panelHeight || CLOSURE_HEIGHT_PX,\n };\n }\n \n // Check if this closure has tubes and trays (closure layout)\n const hasTubes = childNodes.some(n => n.type === 'tube');\n const hasTrays = childNodes.some(n => n.type === 'splice-tray');\n \n let width: number;\n const handleExtension = 5; // Handles extend 5px outside nodes\n \n if (hasTubes && hasTrays) {\n // Closure with tubes and trays\n // Layout: [padding] [left tube] [spacing] [tray] [spacing] [right tube] [handle extension]\n \n // Find the leftmost and rightmost tubes, and trays\n let leftTubeWidth = 0;\n let rightTubeWidth = 0;\n let trayWidth = 0;\n \n // Group tubes by position to determine left vs right\n const tubes = childNodes.filter(n => n.type === 'tube');\n const trays = childNodes.filter(n => n.type === 'splice-tray');\n \n if (tubes.length > 0 && trays.length > 0) {\n // Find leftmost and rightmost tube positions\n const tubePositions = tubes.map(t => t.position?.x || 0);\n const minTubeX = Math.min(...tubePositions);\n const maxTubeX = Math.max(...tubePositions);\n \n // Determine which tubes are left vs right based on position relative to trays\n const trayPositions = trays.map(t => t.position?.x || 0);\n const avgTrayX = trayPositions.reduce((a, b) => a + b, 0) / trayPositions.length;\n \n for (const tube of tubes) {\n const dims = getTubeDimensions(tube);\n const tubeX = tube.position?.x || 0;\n \n if (tubeX < avgTrayX) {\n // Left tube\n if (dims.width > leftTubeWidth) {\n leftTubeWidth = dims.width;\n }\n } else {\n // Right tube\n if (dims.width > rightTubeWidth) {\n rightTubeWidth = dims.width;\n }\n }\n }\n \n // Get tray width\n if (trays.length > 0) {\n trayWidth = TRAY_WIDTH_PX;\n }\n \n // Calculate width: padding + left tube + spacing + tray + spacing + right tube + handle extension\n width = PANEL_PADDING + leftTubeWidth + CLOSURE_TUBE_TRAY_SPACING + trayWidth + CLOSURE_TUBE_TRAY_SPACING + rightTubeWidth + handleExtension;\n } else {\n // Fallback: calculate based on rightmost child\n let maxRight = 0;\n \n for (const child of childNodes) {\n const dims = getNodeDimensions(child);\n const childRight = (child.position?.x || 0) + dims.width;\n \n if (childRight > maxRight) {\n maxRight = childRight;\n }\n }\n \n width = maxRight + PANEL_PADDING + handleExtension;\n }\n } else {\n // Standard layout: calculate based on rightmost child\n let maxRight = 0;\n \n for (const child of childNodes) {\n const dims = getNodeDimensions(child);\n const childRight = (child.position?.x || 0) + dims.width;\n \n if (childRight > maxRight) {\n maxRight = childRight;\n }\n }\n \n // Add padding and handle extension space\n width = maxRight + PANEL_PADDING + handleExtension;\n }\n \n // Ensure width is at least the minimum or explicit width\n width = Math.max(\n closureNode.data?.closureWidth || closureNode.data?.panelWidth || CLOSURE_WIDTH_PX,\n width\n );\n \n // Calculate height based on bottommost child\n let maxBottom = PANEL_HEADER_HEIGHT;\n \n for (const child of childNodes) {\n const dims = getNodeDimensions(child);\n const childBottom = (child.position?.y || 0) + dims.height;\n \n if (childBottom > maxBottom) {\n maxBottom = childBottom;\n }\n }\n \n const height = Math.max(\n closureNode.data?.closureHeight || closureNode.data?.panelHeight || CLOSURE_HEIGHT_PX,\n maxBottom + PANEL_PADDING\n );\n \n return { width, height };\n}\n\n","import React, { useEffect, useMemo, useRef } from 'react';\nimport { NodeProps, useReactFlow } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport {\n PANEL_HEADER_HEIGHT,\n calculatePanelDimensions,\n} from '../utils/coupler-positioning';\n\nexport const PatchPanelNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { label = 'Patch Panel', header, panelWidth: dataWidth, panelHeight: dataHeight } = data || {};\n const { getNodes, setNodes } = useReactFlow();\n const isUpdatingRef = useRef(false);\n \n // Get child nodes - memoized to avoid recalculation\n const childNodes = useMemo(() => {\n const allNodes = getNodes();\n return allNodes.filter((node) => node.parentId === id) as NetworkNode[];\n }, [getNodes, id]);\n \n // Create panel node for dimension calculation\n const panelNode: NetworkNode = useMemo(() => ({\n id,\n type: 'patch-panel',\n position: { x: 0, y: 0 },\n data: { ...data, panelWidth: dataWidth, panelHeight: dataHeight },\n }), [id, data, dataWidth, dataHeight]);\n \n // Calculate dynamic dimensions based on children\n // If explicit width/height is provided, use it (don't recalculate or override)\n const dynamicDimensions = useMemo(() => {\n // If explicit dimensions are provided, ALWAYS use them - never override\n if (dataWidth && dataHeight) {\n return {\n width: dataWidth,\n height: dataHeight,\n };\n }\n \n // Only calculate dynamically if no explicit dimensions provided\n if (childNodes.length === 0) {\n return {\n width: dataWidth || 400,\n height: dataHeight || 300,\n };\n }\n \n return calculatePanelDimensions(panelNode, childNodes as NetworkNode[]);\n }, [childNodes, panelNode, dataWidth, dataHeight]);\n \n // Update panel dimensions in node data when they change (ONLY if no explicit dimensions provided)\n useEffect(() => {\n // Never override explicit dimensions from demo/data\n if (dataWidth && dataHeight) {\n return;\n }\n \n if (isUpdatingRef.current) {\n return;\n }\n \n const currentWidth = dataWidth;\n const currentHeight = dataHeight;\n \n // Only update if dimensions have changed significantly (>1px difference)\n const widthDiff = Math.abs((currentWidth || 0) - dynamicDimensions.width);\n const heightDiff = Math.abs((currentHeight || 0) - dynamicDimensions.height);\n \n if (widthDiff > 1 || heightDiff > 1) {\n isUpdatingRef.current = true;\n setNodes((nodes) =>\n nodes.map((n) =>\n n.id === id\n ? {\n ...n,\n data: {\n ...n.data,\n panelWidth: dynamicDimensions.width,\n panelHeight: dynamicDimensions.height,\n },\n }\n : n\n )\n );\n // Reset flag after a short delay to allow React Flow to process the update\n setTimeout(() => {\n isUpdatingRef.current = false;\n }, 0);\n }\n }, [id, dynamicDimensions.width, dynamicDimensions.height, dataWidth, dataHeight, setNodes]);\n \n // Use dynamic dimensions\n const panelWidth = dynamicDimensions.width;\n const panelHeight = dynamicDimensions.height;\n const headerHeight = PANEL_HEADER_HEIGHT;\n \n const displayHeader = header || label;\n \n return (\n <div\n className={`patch-panel-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'transparent',\n border: 'none',\n borderRadius: '8px',\n padding: 0,\n width: `${panelWidth}px`,\n height: `${panelHeight}px`,\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected\n ? '0 0 0 2px #3b82f6'\n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#1f2937',\n boxSizing: 'border-box',\n }}\n >\n {/* Panel Header */}\n <div\n style={{\n textAlign: 'center',\n marginBottom: 0,\n zIndex: 2,\n background: '#374151',\n padding: '6px 12px',\n position: 'relative',\n height: `${headerHeight}px`,\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '6px',\n borderRadius: '6px 6px 0 0',\n borderBottom: '1px solid #4b5563',\n }}\n >\n <div style={{ fontWeight: 'bold', fontSize: '11px' }}>{displayHeader}</div>\n </div>\n\n {/* Content area where child nodes (couplers, splice-trays) will be placed */}\n <div\n style={{\n position: 'absolute',\n top: headerHeight,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n overflow: 'visible',\n }}\n />\n </div>\n );\n};\n\n","import React, { useEffect, useMemo, useRef } from 'react';\nimport { NodeProps, useReactFlow } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport {\n PANEL_HEADER_HEIGHT,\n calculateClosureDimensions,\n} from '../utils/coupler-positioning';\n\nexport const ClosureNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { label = 'Closure', header, closureWidth: dataWidth, closureHeight: dataHeight, panelWidth, panelHeight } = data || {};\n const { getNodes, setNodes } = useReactFlow();\n const isUpdatingRef = useRef(false);\n \n // Get child nodes - memoized to avoid recalculation\n const childNodes = useMemo(() => {\n const allNodes = getNodes();\n return allNodes.filter((node) => node.parentId === id) as NetworkNode[];\n }, [getNodes, id]);\n \n // Create closure node for dimension calculation\n const closureNode: NetworkNode = useMemo(() => ({\n id,\n type: 'closure',\n position: { x: 0, y: 0 },\n data: { ...data, closureWidth: dataWidth || panelWidth, closureHeight: dataHeight || panelHeight },\n }), [id, data, dataWidth, dataHeight, panelWidth, panelHeight]);\n \n // Calculate dynamic dimensions based on children\n // If explicit width/height is provided, use it (don't recalculate or override)\n const dynamicDimensions = useMemo(() => {\n // If explicit dimensions are provided, ALWAYS use them - never override\n if (dataWidth && dataHeight) {\n return {\n width: dataWidth,\n height: dataHeight,\n };\n }\n \n // Also check panelWidth/panelHeight for backward compatibility\n if (panelWidth && panelHeight) {\n return {\n width: panelWidth,\n height: panelHeight,\n };\n }\n \n // Only calculate dynamically if no explicit dimensions provided\n if (childNodes.length === 0) {\n return {\n width: dataWidth || panelWidth || 400,\n height: dataHeight || panelHeight || 300,\n };\n }\n \n return calculateClosureDimensions(closureNode, childNodes as NetworkNode[]);\n }, [childNodes, closureNode, dataWidth, dataHeight, panelWidth, panelHeight]);\n \n // Update closure dimensions in node data when they change (ONLY if no explicit dimensions provided)\n useEffect(() => {\n // Never override explicit dimensions from demo/data\n if ((dataWidth && dataHeight) || (panelWidth && panelHeight)) {\n return;\n }\n \n if (isUpdatingRef.current) {\n return;\n }\n \n const currentWidth = dataWidth || panelWidth;\n const currentHeight = dataHeight || panelHeight;\n \n // Only update if dimensions have changed significantly (>1px difference)\n const widthDiff = Math.abs((currentWidth || 0) - dynamicDimensions.width);\n const heightDiff = Math.abs((currentHeight || 0) - dynamicDimensions.height);\n \n if (widthDiff > 1 || heightDiff > 1) {\n isUpdatingRef.current = true;\n setNodes((nodes) =>\n nodes.map((n) =>\n n.id === id\n ? {\n ...n,\n data: {\n ...n.data,\n closureWidth: dynamicDimensions.width,\n closureHeight: dynamicDimensions.height,\n },\n }\n : n\n )\n );\n // Reset flag after a short delay to allow React Flow to process the update\n setTimeout(() => {\n isUpdatingRef.current = false;\n }, 0);\n }\n }, [id, dynamicDimensions.width, dynamicDimensions.height, dataWidth, dataHeight, panelWidth, panelHeight, setNodes]);\n \n // Use dynamic dimensions\n const closureWidth = dynamicDimensions.width;\n const closureHeight = dynamicDimensions.height;\n const headerHeight = PANEL_HEADER_HEIGHT;\n \n const displayHeader = header || label;\n \n // Calculate semicircle radius (half the width for a perfect semicircle)\n const semicircleRadius = closureWidth / 2;\n \n return (\n <div\n className={`closure-node ${selected ? 'selected' : ''}`}\n style={{\n background: 'transparent',\n border: 'none',\n borderRadius: `${semicircleRadius}px ${semicircleRadius}px 12px 12px`, // Semicircular top, rounded bottom\n padding: 0,\n width: `${closureWidth}px`,\n height: `${closureHeight}px`,\n color: 'white',\n fontFamily: 'monospace',\n fontSize: '12px',\n boxShadow: selected\n ? '0 0 0 2px #3b82f6'\n : '0 2px 4px rgba(0,0,0,0.1)',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#1f2937', // Same as patch panels\n boxSizing: 'border-box',\n overflow: 'hidden', // Ensure content respects rounded corners\n }}\n >\n {/* Closure Header - Semicircle top */}\n <div\n style={{\n textAlign: 'center',\n marginBottom: 0,\n zIndex: 2,\n background: '#374151',\n padding: '6px 12px',\n position: 'relative',\n height: `${headerHeight}px`,\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '6px',\n borderRadius: `${semicircleRadius}px ${semicircleRadius}px 0 0`, // Semicircle top\n borderBottom: '1px solid #4b5563',\n }}\n >\n <div style={{ fontWeight: 'bold', fontSize: '11px' }}>{displayHeader}</div>\n </div>\n\n {/* Content area where child nodes (splice-trays, tubes) will be placed */}\n <div\n style={{\n position: 'absolute',\n top: headerHeight,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: 'none',\n overflow: 'visible',\n }}\n />\n </div>\n );\n};\n\n","import type { NetworkEdge, NetworkNode } from '../types';\n\nexport type ViewFace = 'front' | 'rear';\n\nexport interface NetworkDiagramState {\n nodes: NetworkNode[];\n edges: NetworkEdge[];\n debug?: boolean;\n}\n\nexport interface ValidateConnectionParams {\n source: string | null;\n target: string | null;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n}\n\nexport interface ValidationResult { valid: boolean; reason?: string }\n\nexport interface NetworkDiagramOptions {\n validateConnection?: (params: ValidateConnectionParams, ctx: NetworkDiagramState) => ValidationResult;\n}\n\nexport interface NetworkDiagramStore {\n getState: () => NetworkDiagramState;\n setState: (partial: Partial<NetworkDiagramState>) => void;\n subscribe: (listener: (state: NetworkDiagramState) => void) => () => void;\n // selectors\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n validateConnection: (params: ValidateConnectionParams) => ValidationResult;\n selectNodeById: (id: string) => NetworkNode | undefined;\n selectConnectedEdges: (nodeId: string) => NetworkEdge[];\n}\n\nfunction defaultValidateConnection(params: ValidateConnectionParams, ctx: NetworkDiagramState): ValidationResult {\n if (!params.source || !params.target || !params.sourceHandle || !params.targetHandle) return { valid: true };\n\n const sourceAlready = ctx.edges.some(e => e.source === params.source && e.sourceHandle === params.sourceHandle);\n const targetAlready = ctx.edges.some(e => e.target === params.target && e.targetHandle === params.targetHandle);\n if (sourceAlready) return { valid: false, reason: 'Source port is already connected' };\n if (targetAlready) return { valid: false, reason: 'Target port is already connected' };\n\n // Enforce basic port-type compatibility: prevent network cables into power ports (and vice versa)\n const sourceHandleId = params.sourceHandle;\n const targetHandleId = params.targetHandle;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const sourceNode = ctx.nodes.find(n => n.id === params.source) as any;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const targetNode = ctx.nodes.find(n => n.id === params.target) as any;\n\n // Treat any power outlet handle on a PDU as power (IDs are numeric), except the explicit mgmt network port\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const isPowerHandle = (h: string, node?: any) => {\n if (!h) return false;\n const looksLikeDevicePower = h.startsWith('pwr') || h.startsWith('power');\n const isPduPower = node?.type === 'vertical-pdu' && h !== 'mgmt-net-1';\n return looksLikeDevicePower || isPduPower;\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const isNetworkHandle = (h: string, node?: any) => {\n if (!h) return false;\n if (node?.type === 'vertical-pdu' && h === 'mgmt-net-1') return true;\n // Tube fiber handles (fiber-1, fiber-2, etc.)\n if (node?.type === 'tube' && h.startsWith('fiber-')) return true;\n if ((node?.type === 'tube' || node?.type === 'cable') && h.startsWith('tube-')) return true;\n // Splice handles (left, right)\n if (node?.type === 'splice' && (h === 'left' || h === 'right')) return true;\n // Check for common network handle patterns\n const looksLikeNetwork = h.startsWith('net-') || h.startsWith('port-') || h.startsWith('uplink-') || h.includes('Fiber') || h.includes('Ports');\n // Check if this is a custom port name from port blocks (e.g., \"QSFP28-1\", \"SFP+-2\", etc.)\n // Custom port names typically follow pattern: \"BlockName-Number\" where BlockName contains port type info\n const isCustomPortName = /^[A-Z0-9]+-\\d+$/.test(h) && !h.startsWith('pwr') && !h.startsWith('power');\n return looksLikeNetwork || isCustomPortName;\n };\n\n const sourceIsPower = isPowerHandle(sourceHandleId, sourceNode);\n const targetIsPower = isPowerHandle(targetHandleId, targetNode);\n const sourceIsNetwork = isNetworkHandle(sourceHandleId, sourceNode);\n const targetIsNetwork = isNetworkHandle(targetHandleId, targetNode);\n\n // If one side is power and the other is network, reject\n if ((sourceIsPower && targetIsNetwork) || (targetIsPower && sourceIsNetwork)) {\n return { valid: false, reason: 'Cannot connect network cable to power port' };\n }\n\n // If one side is explicitly power and the other side is neither power nor network, still reject\n if ((sourceIsPower && !targetIsPower) || (targetIsPower && !sourceIsPower)) {\n return { valid: false, reason: 'Power ports must connect to power-compatible ports' };\n }\n\n // Dual-feed power rule: if a device has two power ports, they must go to different PDUs\n // Identify PDU node and Device node for this connection\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const isPduTarget = targetNode?.type === 'vertical-pdu';\n\n if (sourceIsPower || targetIsPower) {\n const deviceNode = isPduSource ? targetNode : isPduTarget ? sourceNode : null;\n const pduNode = isPduSource ? sourceNode : isPduTarget ? targetNode : null;\n\n // Only enforce if we can identify both sides (PDU <-> device)\n if (deviceNode && pduNode) {\n // Find existing power edges connected to this device\n const devicePowerEdges = ctx.edges.filter(e => {\n const eSourceIsPower = isPowerHandle(e.sourceHandle || '');\n const eTargetIsPower = isPowerHandle(e.targetHandle || '');\n const involvesDevice = e.source === deviceNode.id || e.target === deviceNode.id;\n return (eSourceIsPower || eTargetIsPower) && involvesDevice;\n });\n\n // If there is already a power edge to this device from the same PDU, reject\n const samePduAlready = devicePowerEdges.some(e => e.source === pduNode.id || e.target === pduNode.id);\n if (samePduAlready) {\n // If device has more than one power handle, enforce connecting to the other PDU\n return { valid: false, reason: 'Dual-feed required: connect second power to a different PDU' };\n }\n }\n }\n\n return { valid: true };\n}\n\n// Determine which face a given handle belongs to, based on node data\nexport function getHandleSide(handleId: string, node: NetworkNode | undefined): ViewFace | undefined {\n if (!node) return undefined;\n // Normalize React Flow bidirectional handle suffixes used by patch panels\n // e.g. \"Rear Ports-1-target\" -> \"Rear Ports-1\"\n const normalizedHandleId = typeof handleId === 'string'\n ? handleId.replace(/-(target|source)$/i, '')\n : handleId;\n const data = node.data ?? {};\n\n // Check handleSideMap first if available\n const handleSideMap = (data as { handleSideMap?: Record<string, ViewFace> }).handleSideMap;\n if (handleSideMap && handleSideMap[normalizedHandleId]) {\n return handleSideMap[normalizedHandleId];\n }\n\n // Known defaults\n if (normalizedHandleId === 'net-top' || normalizedHandleId === 'net-bottom') return 'front';\n if (normalizedHandleId === 'pwr-left-1' || normalizedHandleId === 'pwr-left-2' || normalizedHandleId === 'net-right-1' || normalizedHandleId === 'net-right-2') return 'rear';\n\n // Ports from arrays\n const frontBlocks = Array.isArray((data as { ports?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).ports)\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray((data as { rearPorts?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).rearPorts)\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ label: string; type?: string }> }> }).rearPorts!\n : [];\n\n // If the handleId matches a power label, treat as rear by default\n const looksLikePower = normalizedHandleId.startsWith('pwr') || normalizedHandleId.includes('power');\n if (looksLikePower) return 'rear';\n\n // Try to match against front port blocks\n for (const block of frontBlocks) {\n for (const port of block.ports || []) {\n const isPowerPort = !!port.type && String(port.type).includes('power');\n const expected = isPowerPort ? port.label : `${block.name}-${port.label}`;\n if (expected === normalizedHandleId) return 'front';\n }\n }\n // Try to match against rear port blocks\n for (const block of rearBlocks) {\n for (const port of block.ports || []) {\n const isPowerPort = !!port.type && String(port.type).includes('power');\n const expected = isPowerPort ? port.label : `${block.name}-${port.label}`;\n if (expected === normalizedHandleId) return 'rear';\n }\n }\n\n return undefined;\n}\n\nexport function createNetworkDiagramStore(initial: Partial<NetworkDiagramState> = {}, options: NetworkDiagramOptions = {}): NetworkDiagramStore {\n let state: NetworkDiagramState = {\n nodes: initial.nodes ?? [],\n edges: initial.edges ?? [],\n debug: initial.debug ?? false,\n };\n const listeners = new Set<(s: NetworkDiagramState) => void>();\n\n const getState = () => state;\n const setState = (partial: Partial<NetworkDiagramState>) => {\n state = { ...state, ...partial };\n listeners.forEach(l => l(state));\n };\n const subscribe = (listener: (s: NetworkDiagramState) => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n\n const selectEdgeZIndex = (edge: NetworkEdge): number => {\n const targetNode = state.nodes.find(n => n.id === edge.target);\n if (!targetNode || targetNode.type !== 'device') return 1000;\n const deviceView: ViewFace = (targetNode.data?.view as ViewFace) || 'front';\n const side = getHandleSide(edge.targetHandle || '', targetNode);\n if (side) return deviceView === side ? 1000 : 500;\n\n const targetHandle = (edge.targetHandle || '').toString();\n const targetHandleLc = targetHandle.toLowerCase();\n const isPowerHandle = targetHandleLc.startsWith('pwr') || targetHandleLc.startsWith('power');\n const isStandardNetworkHandle = targetHandleLc.startsWith('net-') || targetHandleLc.startsWith('port-') || targetHandleLc.startsWith('uplink-') || targetHandleLc.includes('fiber') || targetHandleLc.includes('ports');\n const isCustomPortName = /^[A-Z0-9]+-\\d+$/i.test(targetHandle) && !targetHandleLc.startsWith('pwr') && !targetHandleLc.startsWith('power');\n const isNetworkHandle = isStandardNetworkHandle || isCustomPortName;\n if (isPowerHandle) return deviceView === 'rear' ? 1000 : 500;\n if (isNetworkHandle) return deviceView === 'front' ? 1000 : 500;\n return 1000;\n };\n\n const validate = (params: ValidateConnectionParams): ValidationResult => {\n const fn = options.validateConnection || defaultValidateConnection;\n return fn(params, state);\n };\n\n const selectNodeById = (id: string) => state.nodes.find(n => n.id === id);\n const selectConnectedEdges = (nodeId: string) => state.edges.filter(e => e.source === nodeId || e.target === nodeId);\n\n return { getState, setState, subscribe, selectEdgeZIndex, validateConnection: validate, selectNodeById, selectConnectedEdges };\n}\n\n\n","import { useSyncExternalStore } from 'react';\nimport type { NetworkEdge, NetworkNode } from '../types';\nimport type { NetworkDiagramStore, NetworkDiagramState, ValidateConnectionParams, ValidationResult } from './store';\n\nexport function useNetworkDiagram(store: NetworkDiagramStore) {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState();\n const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n return state;\n}\n\nexport function useNodes(store: NetworkDiagramStore): NetworkNode[] {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState().nodes;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport function useEdges(store: NetworkDiagramStore): NetworkEdge[] {\n const subscribe = (cb: () => void) => store.subscribe(cb as unknown as (state: NetworkDiagramState) => void);\n const getSnapshot = () => store.getState().edges;\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport function useConnectionValidation(store: NetworkDiagramStore) {\n return (params: ValidateConnectionParams): ValidationResult => store.validateConnection(params);\n}\n\nexport function useSelectEdgeZIndex(store: NetworkDiagramStore) {\n return store.selectEdgeZIndex;\n}\n\n\n","import { NetworkNode } from '../types';\nimport { RACK_WIDTH_PX, U_HEIGHT_PX } from './constants';\n\n/**\n * Calculate the bounding box of a rack node\n * @param rack - The rack node\n * @returns Object with left, right, top, and bottom coordinates\n * @public\n */\nexport function getRackBounds(rack: NetworkNode): {\n left: number;\n right: number;\n top: number;\n bottom: number;\n} {\n const rackWidth = RACK_WIDTH_PX;\n const rackHeight = (rack.data.uHeight || 42) * U_HEIGHT_PX;\n const rackLeft = rack.position.x;\n const rackRight = rack.position.x + rackWidth;\n const rackTop = rack.position.y;\n const rackBottom = rack.position.y + rackHeight;\n\n return {\n left: rackLeft,\n right: rackRight,\n top: rackTop,\n bottom: rackBottom,\n };\n}\n\n/**\n * Check if a point is inside a rack's bounds\n * @param point - The point coordinates { x, y }\n * @param rack - The rack node\n * @returns True if the point is inside the rack\n * @public\n */\nexport function isPointInRack(point: { x: number; y: number }, rack: NetworkNode): boolean {\n const bounds = getRackBounds(rack);\n return (\n point.x >= bounds.left &&\n point.x <= bounds.right &&\n point.y >= bounds.top &&\n point.y <= bounds.bottom\n );\n}\n\n/**\n * Find the nearest rack to a point from a list of racks\n * Only considers racks that contain the point\n * @param point - The point coordinates { x, y }\n * @param racks - Array of rack nodes\n * @returns The nearest rack node, or null if no rack contains the point\n * @public\n */\nexport function findNearestRack(\n point: { x: number; y: number },\n racks: NetworkNode[]\n): NetworkNode | null {\n let nearestRack: NetworkNode | null = null;\n let minDistance = Infinity;\n\n for (const rack of racks) {\n if (!isPointInRack(point, rack)) {\n continue;\n }\n\n const distance = Math.sqrt(\n Math.pow(point.x - rack.position.x, 2) + Math.pow(point.y - rack.position.y, 2)\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n nearestRack = rack;\n }\n }\n\n return nearestRack;\n}\n\n","import { Connection, Edge, addEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\n\n/**\n * Options for replacing an edge in the edges array\n */\nexport interface ReplaceEdgeOptions {\n /** Existing edges array */\n edges: Edge[];\n /** Connection parameters for the new edge */\n connection: Connection;\n /** Type of edge to create */\n edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable';\n /** Function to calculate zIndex for the edge */\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n /** Whether to find edge by source or target */\n findBy: 'source' | 'target';\n /** Optional edge data to set on the new edge */\n data?: NetworkEdge['data'];\n}\n\n/**\n * Replace an existing edge with a new connection\n * This is used for PDU and switch connections that allow replacing existing edges\n * @param options - Options for edge replacement\n * @returns New edges array with the edge replaced, or null if no existing edge found\n * @public\n */\nexport function replaceEdge(\n options: ReplaceEdgeOptions\n): Edge[] | null {\n const { edges, connection, edgeType, selectEdgeZIndex, findBy, data } = options;\n\n // Determine which handle to search by\n const handleId = findBy === 'source' ? connection.sourceHandle : connection.targetHandle;\n const nodeId = findBy === 'source' ? connection.source : connection.target;\n\n if (!handleId || !nodeId) {\n return null;\n }\n\n // Find existing edge\n const existingEdge = edges.find(e => {\n if (findBy === 'source') {\n return e.source === nodeId && e.sourceHandle === handleId;\n } else {\n return e.target === nodeId && e.targetHandle === handleId;\n }\n });\n\n if (!existingEdge) {\n return null;\n }\n\n // Remove the existing edge\n const filtered = edges.filter(e => e.id !== existingEdge.id);\n\n // Create new edge using addEdge helper, then add type and zIndex\n const edgeFromAddEdge = addEdge(connection, filtered);\n \n // Find the newly added edge and update it with type, zIndex, and data\n const newEdge = edgeFromAddEdge[edgeFromAddEdge.length - 1];\n const zIndex = selectEdgeZIndex({ ...connection, id: newEdge.id, type: edgeType } as NetworkEdge);\n const edgeWithMetadata: Edge = {\n ...newEdge,\n type: edgeType,\n zIndex: zIndex,\n style: { ...newEdge.style, zIndex: zIndex },\n data: data !== undefined ? data : newEdge.data,\n };\n\n // Replace the last edge with the one that has metadata\n return [...edgeFromAddEdge.slice(0, -1), edgeWithMetadata];\n}\n\n","import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react';\nimport {\n ReactFlow,\n Background,\n Controls,\n MiniMap,\n useNodesState,\n useEdgesState,\n addEdge,\n Connection,\n Edge,\n Node,\n NodeTypes,\n EdgeTypes,\n useReactFlow,\n NodeChange,\n useOnSelectionChange,\n ReactFlowProvider,\n Panel,\n NodeProps,\n} from 'reactflow';\nimport { toPng } from 'html-to-image';\nimport { NetworkDiagramProps, NetworkNode, NetworkEdge } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from '../utils/constants';\nimport { RackNode } from './RackNode';\nimport { FiberNode } from './FiberNode';\nimport { FiberEdge } from './FiberEdge';\nimport { PowerEdge } from './PowerEdge';\nimport { SmoothStepFiberEdge } from './SmoothStepFiberEdge';\nimport { StepFiberEdge } from './StepFiberEdge';\nimport { ThickCableEdge } from './ThickCableEdge';\nimport { DeviceNode } from './DeviceNode';\nimport { VerticalPDU } from './VerticalPDU';\nimport { SpliceNode } from './SpliceNode';\nimport { SpliceTrayNode } from './SpliceTrayNode';\nimport { TubeNode } from './TubeNode';\nimport { CableNode } from './CableNode';\nimport { CouplerNode } from './CouplerNode';\nimport { PatchPanelNode } from './PatchPanelNode';\nimport { ClosureNode } from './ClosureNode';\nimport { snapToUPosition, calculateDevicePositionFromU } from '../utils/u-positioning';\nimport { createNetworkDiagramStore, getHandleSide } from '../core/store';\nimport { useEdges, useNodes, useSelectEdgeZIndex } from '../core/hooks';\nimport { isPointInRack, findNearestRack } from '../utils/rack-geometry';\nimport { replaceEdge } from '../utils/edge-connection';\nimport { getFiberColor, baseColorFor } from '../utils/fiber-colors';\nimport { snapToSplicePosition, calculateSplicePositionFromNumber } from '../utils/splice-positioning';\n\n// Create nodeTypes with onViewChange prop - memoized outside component\nconst createNodeTypes = (\n onViewChange?: (nodeId: string, view: 'front' | 'rear') => void,\n onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void,\n getDragOverRackId?: () => string | null\n): NodeTypes => ({\n rack: (props: NodeProps<NetworkNode['data']>) => <RackNode {...props} onViewChange={onViewChange} onRackFaceChange={onRackFaceChange} isDragOver={getDragOverRackId ? getDragOverRackId() === props.id : false} />,\n fiber: FiberNode,\n device: DeviceNode,\n 'vertical-pdu': VerticalPDU,\n splice: SpliceNode,\n 'splice-tray': SpliceTrayNode,\n tube: TubeNode,\n cable: CableNode,\n coupler: CouplerNode,\n 'patch-panel': PatchPanelNode,\n closure: ClosureNode,\n});\n\nconst edgeTypes: EdgeTypes = {\n fiber: FiberEdge,\n power: PowerEdge,\n smoothstep: SmoothStepFiberEdge,\n step: StepFiberEdge,\n 'thick-cable': ThickCableEdge,\n};\n\nconst NetworkDiagramInner: React.FC<NetworkDiagramProps> = ({\n nodes,\n edges,\n initialNodes,\n initialEdges,\n onNodesChange: externalOnNodesChange,\n onEdgesChange: externalOnEdgesChange,\n store,\n debug,\n onNodeClick,\n onEdgeClick,\n onViewChange,\n onRackFaceChange,\n className,\n style,\n alignRacksToBottom,\n colorMode = 'dark',\n onInit,\n onFlowMethods,\n showDownloadButton = false,\n downloadButtonPosition = 'top-right',\n downloadButtonText = 'Download Image',\n downloadButtonStyle,\n allowReconnectExisting = false,\n useSmoothstepEdgesForTubes = false,\n}) => {\n // Decide controlled vs uncontrolled\n const isControlled = Array.isArray(nodes) && Array.isArray(edges);\n // Important: do not recreate store on nodes/edges changes to avoid perceived resets\n const localStore = React.useMemo(() => {\n if (store) return store;\n // Create store once; controlled updates will sync via effects below\n return createNetworkDiagramStore({\n nodes: isControlled ? (nodes || []) : (initialNodes || nodes || []),\n edges: isControlled ? (edges || []) : (initialEdges || edges || []),\n debug,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store, isControlled, debug]);\n\n // Local React Flow states mirror store state for rendering\n const storeNodes = useNodes(localStore);\n const storeEdges = useEdges(localStore);\n const [reactFlowNodes, setNodes, onNodesChange] = useNodesState(storeNodes);\n const [reactFlowEdges, setEdges, onEdgesChange] = useEdgesState(storeEdges);\n const selectEdgeZIndex = useSelectEdgeZIndex(localStore);\n const reactFlowWrapper = useRef<HTMLDivElement>(null);\n \n // Get React Flow methods for save/restore\n const { toObject, setViewport, setNodes: setReactFlowNodes, setEdges: setReactFlowEdges, getNodes } = useReactFlow();\n \n // Type for html-to-image options\n interface ToImageOptions {\n width?: number;\n height?: number;\n backgroundColor?: string;\n padding?: number;\n pixelRatio?: number;\n quality?: number;\n filter?: (domNode: HTMLElement) => boolean;\n }\n \n // Expose React Flow methods to parent component\n useEffect(() => {\n if (onFlowMethods) {\n onFlowMethods({\n toObject,\n setViewport,\n setNodes: (nodes: Node[]) => {\n setReactFlowNodes(nodes);\n localStore.setState({ nodes: nodes as NetworkNode[] });\n },\n setEdges: (edges: Edge[]) => {\n setReactFlowEdges(edges);\n localStore.setState({ edges: edges as NetworkEdge[] });\n },\n toImage: (options?: ToImageOptions) => {\n if (!reactFlowWrapper.current) return Promise.reject(new Error('ReactFlow wrapper not available'));\n return toPng(reactFlowWrapper.current, options);\n }\n });\n }\n }, [onFlowMethods, toObject, setViewport, setReactFlowNodes, setReactFlowEdges, localStore]);\n\n // Download functionality\n const onDownload = useCallback(() => {\n if (!reactFlowWrapper.current) {\n if (debug) {\n console.error('ReactFlow wrapper ref is not available');\n }\n return;\n }\n \n toPng(reactFlowWrapper.current, {\n filter: (node) =>\n !(\n node?.classList?.contains('react-flow__minimap') ||\n node?.classList?.contains('react-flow__controls') ||\n node?.classList?.contains('react-flow__attribution') ||\n node?.classList?.contains('download-button') ||\n node?.tagName === 'BUTTON'\n ),\n backgroundColor: colorMode === 'light' ? '#ffffff' : '#1a1a1a',\n pixelRatio: 2,\n }).then((dataUrl: string) => {\n const link = document.createElement('a');\n link.download = `network-diagram-${new Date().toISOString().split('T')[0]}.png`;\n link.href = dataUrl;\n link.click();\n }).catch((error: unknown) => {\n if (debug) {\n console.error('Error downloading image:', error);\n }\n });\n }, [colorMode, debug]);\n \n // Track which rack is being dragged over for visual feedback\n const [dragOverRackId, setDragOverRackId] = useState<string | null>(null);\n const dragOverRackIdRef = useRef<string | null>(null);\n \n // Store callbacks in refs to keep nodeTypes stable even if callbacks change\n const onViewChangeRef = useRef(onViewChange);\n const onRackFaceChangeRef = useRef(onRackFaceChange);\n \n // Update refs when callbacks change\n useEffect(() => {\n onViewChangeRef.current = onViewChange;\n }, [onViewChange]);\n \n useEffect(() => {\n onRackFaceChangeRef.current = onRackFaceChange;\n }, [onRackFaceChange]);\n \n // Update ref when state changes\n useEffect(() => {\n dragOverRackIdRef.current = dragOverRackId;\n }, [dragOverRackId]);\n \n // Memoize nodeTypes to avoid recreating object every render (prevents node remounts)\n // Use refs for callbacks to keep nodeTypes stable even if callbacks change\n // CRITICAL: Must use a stable function reference, not calling .current\n const getDragOverRackIdStable = useCallback(() => dragOverRackIdRef.current, []);\n const memoizedNodeTypes = useMemo(\n () => createNodeTypes(\n (nodeId, view) => onViewChangeRef.current?.(nodeId, view),\n (rackId, face) => onRackFaceChangeRef.current?.(rackId, face),\n getDragOverRackIdStable\n ),\n [getDragOverRackIdStable] // Only recreate if the stable function changes (it won't)\n );\n \n // Memoize edgeTypes to prevent recreation warnings\n const memoizedEdgeTypes = useMemo(() => edgeTypes, []);\n\n\n // Maintain the latest nodes in a ref for always-current lookups in callbacks\n const latestNodesRef = useRef<Node[]>(reactFlowNodes);\n useEffect(() => { latestNodesRef.current = reactFlowNodes; }, [reactFlowNodes]);\n\n // Maintain the latest edges in a ref for always-current lookups in callbacks\n const latestEdgesRef = useRef<Edge[]>(reactFlowEdges);\n useEffect(() => { latestEdgesRef.current = reactFlowEdges; }, [reactFlowEdges]);\n\n // Sync store -> RF state updates\n useEffect(() => { setNodes(storeNodes); }, [storeNodes, setNodes]);\n useEffect(() => { setEdges(storeEdges); }, [storeEdges, setEdges]);\n // Sync controlled props -> store (if controlled)\n useEffect(() => {\n if (isControlled) {\n localStore.setState({ nodes: nodes || [] });\n }\n }, [isControlled, nodes, localStore]);\n useEffect(() => {\n if (isControlled) {\n localStore.setState({ edges: edges || [] });\n }\n }, [isControlled, edges, localStore]);\n\n // Optionally align rack bottoms to a common baseline\n useEffect(() => {\n if (!alignRacksToBottom) return;\n if (!reactFlowNodes || reactFlowNodes.length === 0) return;\n\n const racks = reactFlowNodes.filter(n => n.type === 'rack');\n if (racks.length === 0) return;\n\n // Compute each rack's bottom (y + header + uHeight * U_HEIGHT_PX)\n const rackBottoms = racks.map(r => {\n const rackData = r.data as NetworkNode['data'];\n const uHeight = rackData?.uHeight || 42;\n const heightPx = RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX;\n return (r.position?.y || 0) + heightPx;\n });\n \n // Find the range of bottom positions\n const minBottom = Math.min(...rackBottoms);\n const maxBottom = Math.max(...rackBottoms);\n const range = maxBottom - minBottom;\n \n // Only align if there's a significant difference (more than 20px)\n // This prevents constant micro-adjustments during dragging\n if (range < 20) return;\n \n // Use the highest bottom as the baseline (floor level)\n const baselineBottom = maxBottom;\n\n // Align all racks to the baseline - move them up or down as needed\n const nextNodes = reactFlowNodes.map(n => {\n if (n.type !== 'rack') return n;\n const nodeData = n.data as NetworkNode['data'];\n const uHeight = nodeData?.uHeight || 42;\n const heightPx = RACK_HEADER_HEIGHT + uHeight * U_HEIGHT_PX;\n const currentBottom = (n.position?.y || 0) + heightPx;\n const delta = baselineBottom - currentBottom;\n if (Math.abs(delta) < 5) return n; // Don't make tiny adjustments\n return {\n ...n,\n position: {\n x: n.position?.x || 0,\n y: (n.position?.y || 0) + delta,\n },\n } as Node;\n });\n\n const changed = nextNodes.some((n, i) => n.position !== reactFlowNodes[i].position);\n if (changed) setNodes(nextNodes);\n }, [alignRacksToBottom, reactFlowNodes, setNodes]);\n\n // Helper: always get current version of a node (beyond closure scope issue)\n const getNodeById = useCallback((id: string) => {\n return latestNodesRef.current.find(n => n.id === id);\n }, []);\n\n // Helper: derive fiber color from source node handle\n // For tube nodes: handle ID is \"fiber-<n>\" where n is 1-24, use TIA color\n // For cable nodes: handle ID is \"tube-<n>\" representing buffer tubes (1-24), use tube color\n // For tube-to-cable connections: hidden handles share the same \"tube-<n>\" pattern\n // For other nodes: check node data color\n const deriveFiberColorFromSource = useCallback((sourceNodeId: string, sourceHandle: string | null | undefined): { color: string; striped?: boolean } | undefined => {\n if (!sourceNodeId || !sourceHandle) return undefined;\n const sourceNode = getNodeById(sourceNodeId);\n if (!sourceNode) return undefined;\n \n // For tube nodes, extract fiber number from handle ID (format: \"fiber-<n>\")\n if (sourceNode.type === 'tube' && sourceHandle.startsWith('fiber-')) {\n const fiberNumStr = sourceHandle.replace('fiber-', '');\n const fiberNum = parseInt(fiberNumStr, 10);\n if (fiberNum >= 1 && fiberNum <= 24) {\n const color = getFiberColor(fiberNum);\n const striped = fiberNum > 12;\n return { color, striped };\n }\n }\n\n if ((sourceNode.type === 'cable' || sourceNode.type === 'tube') && sourceHandle.startsWith('tube-')) {\n const tubeNumStr = sourceHandle.replace('tube-', '');\n const tubeNum = parseInt(tubeNumStr, 10);\n if (tubeNum >= 1 && tubeNum <= 24) {\n const color = baseColorFor(tubeNum);\n const striped = tubeNum > 12;\n return { color, striped };\n }\n }\n \n // For other node types, check node data color\n const nodeData = sourceNode.data as NetworkNode['data'];\n if (nodeData.color) {\n return { color: nodeData.color };\n }\n \n return undefined;\n }, [getNodeById]);\n\n // Update edges zIndex when nodes change\n useEffect(() => {\n setEdges((eds) =>\n eds.map(edge => {\n const newZIndex = selectEdgeZIndex(edge as NetworkEdge);\n return {\n ...edge,\n zIndex: newZIndex,\n style: { ...edge.style, zIndex: newZIndex }\n };\n })\n );\n }, [reactFlowNodes, setEdges, selectEdgeZIndex]);\n\n useEffect(() => {\n const updatedNodes = reactFlowNodes.map(node => {\n // Ensure extent is set for couplers in panels (no repositioning - they're not movable)\n if (\n node.type === 'coupler' &&\n node.parentId\n ) {\n const parentPanel = getNodeById(node.parentId);\n if (parentPanel && (parentPanel.type === 'patch-panel' || parentPanel.type === 'closure')) {\n // Ensure extent is set for proper parent-child relationship\n if (!node.extent || node.extent !== 'parent') {\n return {\n ...node,\n extent: 'parent' as const,\n };\n }\n }\n }\n // Handle splice positioning\n if (\n node.type === 'splice' &&\n node.parentId &&\n node.data.holderPosition &&\n (!node.position || (node.position.x === 0 && node.position.y === 0))\n ) {\n const parentTray = getNodeById(node.parentId);\n if (parentTray && parentTray.type === 'splice-tray') {\n const calculatedPosition = calculateSplicePositionFromNumber(parentTray as NetworkNode, node.data.holderPosition);\n return {\n ...node,\n position: calculatedPosition,\n };\n }\n }\n // Handle device positioning\n if (\n node.type === 'device' &&\n node.parentId &&\n node.data.uPosition &&\n (!node.position || (node.position.x === 0 && node.position.y === 0))\n ) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const calculatedPosition = calculateDevicePositionFromU(parentRack as NetworkNode, node.data.uPosition);\n return {\n ...node,\n position: calculatedPosition,\n };\n }\n }\n return node;\n });\n\n const hasChanges = updatedNodes.some((node, index) => {\n const originalNode = reactFlowNodes[index];\n return (\n node.extent !== originalNode.extent ||\n node.position?.x !== originalNode.position?.x ||\n node.position?.y !== originalNode.position?.y\n );\n });\n if (hasChanges) {\n setNodes(updatedNodes);\n }\n }, [reactFlowNodes, setNodes, getNodeById]);\n\n const handleNodesChange = useCallback((changes: NodeChange[]) => {\n const updatedChanges = changes.map((change) => {\n if (change.type === 'position' && change.position) {\n const node = getNodeById(change.id);\n\n // Prevent couplers from being moved (they're fixed in position)\n if (node && node.type === 'coupler' && node.parentId) {\n const parentPanel = getNodeById(node.parentId);\n if (parentPanel && (parentPanel.type === 'patch-panel' || parentPanel.type === 'closure')) {\n // Ensure extent is set for proper parent-child relationship\n if (!node.extent || node.extent !== 'parent') {\n const updatedNode = {\n ...node,\n extent: 'parent' as const,\n };\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n }\n \n // Prevent movement by returning original position\n return { ...change, position: node.position || { x: 0, y: 0 } };\n }\n }\n\n // Handle splice positioning within tray\n if (node && node.type === 'splice' && node.parentId) {\n const parentTray = getNodeById(node.parentId);\n if (parentTray && parentTray.type === 'splice-tray') {\n const snappedResult = snapToSplicePosition(\n node as NetworkNode,\n parentTray as NetworkNode,\n change.position,\n latestNodesRef.current as NetworkNode[]\n );\n\n if (snappedResult.holderPosition !== undefined) {\n const updatedNode = {\n ...node,\n data: {\n ...node.data,\n holderPosition: snappedResult.holderPosition,\n },\n };\n\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n // Handle device positioning within rack\n if (node && node.type === 'device' && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const snappedResult = snapToUPosition(\n node as NetworkNode,\n parentRack as NetworkNode,\n change.position,\n latestNodesRef.current as NetworkNode[]\n );\n\n if (snappedResult.uPosition !== undefined) {\n const updatedNode = {\n ...node,\n data: {\n ...node.data,\n uPosition: snappedResult.uPosition,\n },\n };\n\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n\n if (node && node.type === 'device' && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack) {\n const rackNode = parentRack as NetworkNode;\n\n if (!isPointInRack(change.position, rackNode)) {\n const absoluteX = change.position.x + rackNode.position.x;\n const absoluteY = change.position.y + rackNode.position.y;\n const updatedNode = {\n ...node,\n parentId: undefined,\n extent: undefined,\n data: {\n ...node.data,\n uPosition: undefined,\n },\n };\n setNodes((nodes) =>\n nodes.map(n => n.id === node.id ? updatedNode : n)\n );\n return { ...change, position: { x: absoluteX, y: absoluteY } };\n }\n }\n }\n }\n return change;\n });\n\n onNodesChange(updatedChanges);\n }, [onNodesChange, setNodes, getNodeById]);\n\n // Handle drag start to track which node is being dragged\n const handleNodeDragStart = useCallback((_event: React.MouseEvent, _node: Node) => {\n // Reset drag over state when starting a new drag\n setDragOverRackId(null);\n }, []);\n\n // Handle drag over to detect when device is over a rack\n const handleNodeDrag = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n if (node.type === 'device' && !node.parentId) {\n // Find the nearest rack\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const nearestRack = findNearestRack(node.position, racks);\n\n // Update drag over state\n setDragOverRackId(nearestRack?.id ?? null);\n } else {\n setDragOverRackId(null);\n }\n }, []);\n\n // Handle drag end to group ungrouped nodes into racks\n const handleNodeDragStop = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n if (node.type === 'device' && !node.parentId) {\n // Find the nearest rack\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const nearestRack = findNearestRack(node.position, racks);\n\n if (nearestRack) {\n // Calculate relative position\n const relativeX = node.position.x - nearestRack.position.x;\n const relativeY = node.position.y - nearestRack.position.y;\n \n // Update the node with parent relationship and new position\n const updatedNode = {\n ...node,\n parentId: nearestRack.id,\n extent: 'parent' as const,\n position: { x: relativeX, y: relativeY },\n data: {\n ...node.data,\n uPosition: 1,\n },\n };\n \n const updatedNodes = latestNodesRef.current.map(n => n.id === node.id ? updatedNode : n);\n setNodes(updatedNodes);\n \n // Update store in uncontrolled mode\n if (!isControlled) {\n localStore.setState({ nodes: updatedNodes as NetworkNode[] });\n }\n }\n }\n \n // Clear drag over state when drag ends\n setDragOverRackId(null);\n }, [setNodes, isControlled, localStore]);\n\n // Connection validation for React Flow - allows connections before onConnect validation\n const isValidConnection = useCallback((connection: Connection): boolean => {\n if (!connection.source || !connection.target || !connection.sourceHandle || !connection.targetHandle) {\n return true;\n }\n\n const sourceNode = getNodeById(connection.source);\n const targetNode = getNodeById(connection.target);\n\n // Prevent connections between fibres in tubes (both source and target are tube nodes with fiber handles)\n if (\n sourceNode?.type === 'tube' &&\n targetNode?.type === 'tube' &&\n connection.sourceHandle.startsWith('fiber-') &&\n connection.targetHandle.startsWith('fiber-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect fibres within tubes', connection);\n }\n return false;\n }\n\n // Prevent individual fibre connections to cable tube handles\n // Tube fiber handles (fiber-*) should not connect to cable/tube tube handles (tube-*)\n if (\n sourceNode?.type === 'tube' &&\n connection.sourceHandle.startsWith('fiber-') &&\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n connection.targetHandle.startsWith('tube-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect individual fibre to cable/tube tube handle', connection);\n }\n return false;\n }\n\n // Prevent cable/tube tube handles from connecting to individual fibre handles\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n connection.sourceHandle.startsWith('tube-') &&\n targetNode?.type === 'tube' &&\n connection.targetHandle.startsWith('fiber-')\n ) {\n if (debug) {\n console.log('Connection rejected: Cannot connect cable/tube tube handle to individual fibre', connection);\n }\n return false;\n }\n\n // Check if splice target handle is already connected - only allow one edge per handle\n if (targetNode?.type === 'splice' && (connection.targetHandle === 'left' || connection.targetHandle === 'right')) {\n // Check both target and source (right handle can be either)\n const existingEdge = latestEdgesRef.current.find(\n (e) => (e.target === connection.target && e.targetHandle === connection.targetHandle) ||\n (e.source === connection.target && e.sourceHandle === connection.targetHandle)\n );\n if (existingEdge) {\n if (debug) {\n console.log('Splice handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n // No existing edge - allow connection (will be handled by general check below)\n if (debug) {\n console.log('Allowing connection to splice handle', connection);\n }\n // Continue to general check below to ensure no other edges exist\n }\n\n // Check if tube fiber source handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube fiber handles (fiber-*) can ONLY connect to splices\n if (sourceNode?.type === 'tube' && connection.sourceHandle.startsWith('fiber-')) {\n // Validate that fiber handles can only connect to splices\n if (targetNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Tube fiber handles can only connect to splices', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube fiber handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube fiber handle to splice', connection);\n }\n return true;\n }\n\n // Check if cable/tube tube-level source handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube handles (tube-*) can ONLY connect to other tube handles (tube-*)\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n connection.sourceHandle.startsWith('tube-')\n ) {\n // Validate that tube handles can only connect to other tube handles\n if (!connection.targetHandle.startsWith('tube-')) {\n if (debug) {\n console.log('Connection rejected: Tube handles can only connect to other tube handles', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube-level handle already connected, will replace', connection);\n }\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube-level handle to tube handle', connection);\n }\n return true;\n }\n\n // Check if splice source handle is already connected - only allow one edge per handle\n if (sourceNode?.type === 'splice' && connection.sourceHandle === 'right') {\n // Check both source and target (right handle can be either)\n const existingEdge = latestEdgesRef.current.find(\n (e) => (e.source === connection.source && e.sourceHandle === connection.sourceHandle) ||\n (e.target === connection.source && e.targetHandle === connection.sourceHandle)\n );\n if (existingEdge) {\n if (debug) {\n console.log('Splice source handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n // No existing edge - continue to general check below to ensure no other edges exist\n if (debug) {\n console.log('Allowing connection from splice source handle', connection);\n }\n // Continue to general check below\n }\n\n // Check if tube fiber target handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube fiber handles (fiber-*) can ONLY connect to splices\n if (targetNode?.type === 'tube' && connection.targetHandle.startsWith('fiber-')) {\n // Validate that fiber handles can only connect from splices\n if (sourceNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Tube fiber handles can only connect from splices', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube fiber target handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from splice to tube fiber handle', connection);\n }\n return true;\n }\n\n // Check if cable/tube tube-level target handle is already connected - only allow one edge per handle\n // IMPORTANT: Tube handles (tube-*) can ONLY connect to other tube handles (tube-*)\n if (\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n connection.targetHandle.startsWith('tube-')\n ) {\n // Validate that tube handles can only connect from other tube handles\n if (!connection.sourceHandle.startsWith('tube-')) {\n if (debug) {\n console.log('Connection rejected: Tube handles can only connect from other tube handles', connection);\n }\n return false;\n }\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Tube-level target handle already connected, will replace', connection);\n }\n return true;\n }\n if (debug) {\n console.log('Allowing connection from tube handle to tube-level handle', connection);\n }\n return true;\n }\n\n // Check if coupler handle is connecting - only allow connections to splices\n if (sourceNode?.type === 'coupler' && (connection.sourceHandle?.startsWith('left-') || connection.sourceHandle?.startsWith('right-'))) {\n // Validate that coupler handles can only connect to splices\n if (targetNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Coupler handles can only connect to splices', connection);\n }\n return false;\n }\n // Validate that splice handles are 'left' or 'right'\n if (connection.targetHandle !== 'left' && connection.targetHandle !== 'right') {\n if (debug) {\n console.log('Connection rejected: Coupler can only connect to splice left/right handles', connection);\n }\n return false;\n }\n // Check if coupler handle is already connected - only allow one edge per handle\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Coupler handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from coupler handle to splice', connection);\n }\n return true;\n }\n\n // Check if coupler target handle is connecting - only allow connections from splices\n if (targetNode?.type === 'coupler' && (connection.targetHandle?.startsWith('left-') || connection.targetHandle?.startsWith('right-'))) {\n // Validate that coupler handles can only connect from splices\n if (sourceNode?.type !== 'splice') {\n if (debug) {\n console.log('Connection rejected: Coupler handles can only connect from splices', connection);\n }\n return false;\n }\n // Validate that splice handles are 'left' or 'right'\n if (connection.sourceHandle !== 'left' && connection.sourceHandle !== 'right') {\n if (debug) {\n console.log('Connection rejected: Coupler can only connect from splice left/right handles', connection);\n }\n return false;\n }\n // Check if coupler handle is already connected - only allow one edge per handle\n const existingEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingEdge) {\n if (debug) {\n console.log('Coupler target handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n if (debug) {\n console.log('Allowing connection from splice to coupler handle', connection);\n }\n return true;\n }\n\n // GENERAL CHECK: Ensure ALL handles only allow one connection\n // This must run BEFORE store validation to catch all cases\n // Check if source handle already has a connection\n if (connection.source && connection.sourceHandle) {\n const existingSourceEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingSourceEdge) {\n if (debug) {\n console.log('Source handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n }\n\n // Check if target handle already has a connection\n if (connection.target && connection.targetHandle) {\n const existingTargetEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingTargetEdge) {\n if (debug) {\n console.log('Target handle already connected, will replace', connection);\n }\n // Allow the connection - onConnect will handle replacement\n return true;\n }\n }\n\n // Check if cable button handle is already connected - only allow one edge per handle\n // Button handles (cable-button) can only connect to other cable button handles\n if (\n (sourceNode?.type === 'cable' || targetNode?.type === 'cable') &&\n (connection.sourceHandle === 'cable-button' || connection.targetHandle === 'cable-button')\n ) {\n // Validate that button handles can only connect to other button handles\n if (connection.sourceHandle !== 'cable-button' || connection.targetHandle !== 'cable-button') {\n if (debug) {\n console.log('Connection rejected: Cable button handles can only connect to other cable button handles', connection);\n }\n return false;\n }\n // Check if source handle is already connected\n const existingSourceEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (existingSourceEdge) {\n if (debug) {\n console.log('Cable button source handle already connected, will replace', connection);\n }\n return true;\n }\n // Check if target handle is already connected\n const existingTargetEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (existingTargetEdge) {\n if (debug) {\n console.log('Cable button target handle already connected, will replace', connection);\n }\n return true;\n }\n if (debug) {\n console.log('Allowing connection between cable button handles', connection);\n }\n return true;\n }\n\n // For all other connections, use the store validation (which also recognizes tube/splice as network)\n const validation = localStore.validateConnection({\n source: connection.source ?? null,\n target: connection.target ?? null,\n sourceHandle: connection.sourceHandle ?? null,\n targetHandle: connection.targetHandle ?? null,\n });\n\n // If validation fails but allowReconnectExisting is enabled, check if there's an existing edge\n // on either the source or target handle that we can replace\n if (!validation.valid && allowReconnectExisting) {\n // Check if source handle has an existing edge\n if (connection.source && connection.sourceHandle) {\n const sourceEdge = latestEdgesRef.current.find(\n (e) => e.source === connection.source && e.sourceHandle === connection.sourceHandle\n );\n if (sourceEdge) {\n if (debug) {\n console.log('Source handle has existing edge, will replace', connection);\n }\n return true;\n }\n }\n // Check if target handle has an existing edge\n if (connection.target && connection.targetHandle) {\n const targetEdge = latestEdgesRef.current.find(\n (e) => e.target === connection.target && e.targetHandle === connection.targetHandle\n );\n if (targetEdge) {\n if (debug) {\n console.log('Target handle has existing edge, will replace', connection);\n }\n return true;\n }\n }\n }\n\n if (debug && !validation.valid) {\n console.log('Connection rejected by store validation:', validation.reason, connection);\n }\n\n return validation.valid;\n }, [getNodeById, localStore, debug, allowReconnectExisting]);\n\n const onConnect = useCallback(\n (params: Connection) => {\n const sourceNode = getNodeById(params.source!);\n const targetNode = getNodeById(params.target!);\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const isSwitchSource = sourceNode?.type === 'device' && sourceNodeData?.deviceType === 'switch';\n const looksLikePowerTarget = !!params.targetHandle && (params.targetHandle.startsWith('pwr') || params.targetHandle.startsWith('power'));\n const looksLikeNetworkTarget = !!params.targetHandle && (\n params.targetHandle.startsWith('net-') || \n params.targetHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(params.targetHandle) // Custom port names like \"QSFP28-1\"\n );\n\n // Determine edge type: step for tube > cable, power for PDU connections, thick-cable for button handles, fiber otherwise\n const isTubeToCable = sourceNode?.type === 'tube' && targetNode?.type === 'cable';\n const isCableToTube = sourceNode?.type === 'cable' && targetNode?.type === 'tube';\n const isTubeConnection = isTubeToCable || isCableToTube;\n const isButtonHandleConnection = params.sourceHandle === 'cable-button' && params.targetHandle === 'cable-button';\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable' = 'fiber';\n if (isPduSource && looksLikePowerTarget) {\n edgeType = 'power';\n } else if (isButtonHandleConnection) {\n edgeType = 'thick-cable';\n } else if (isTubeConnection) {\n // Use smoothstep edges if useSmoothstepEdgesForTubes is true, otherwise use fiber (default)\n edgeType = useSmoothstepEdgesForTubes ? 'smoothstep' : 'fiber';\n }\n \n // Derive fiber color from source node handle (for fiber/smoothstep edges)\n let edgeData: { color?: string; striped?: boolean } | undefined;\n if ((edgeType === 'fiber' || edgeType === 'smoothstep') && !isPduSource) {\n const colorInfo = deriveFiberColorFromSource(params.source!, params.sourceHandle);\n if (colorInfo) {\n edgeData = { color: colorInfo.color, striped: colorInfo.striped };\n }\n } else if (edgeType === 'thick-cable' && isButtonHandleConnection) {\n // For thick-cable edges, get color from source cable node\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const cableColor = sourceNodeData?.color || (sourceNodeData?.tubeStartIndex ? baseColorFor(sourceNodeData.tubeStartIndex) : '#6366f1');\n edgeData = { color: cableColor };\n }\n\n // GENERAL REPLACEMENT: Replace existing edge on ANY handle - ensure all handles only allow one connection\n // Try replacing from source handle first\n if (params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n // Try replacing from target handle\n if (params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on splice target handle (left or right) - only one edge per handle\n // Right handle can be either source or target, so check both\n if (targetNode?.type === 'splice' && (params.targetHandle === 'left' || params.targetHandle === 'right') && params.target && params.targetHandle) {\n // Try replacing as target first\n let newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n // If right handle and not found as target, try as source (right handle can be either)\n if (params.targetHandle === 'right') {\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n }\n\n // Replace existing edge on splice source handle (right) - only one edge per handle\n // Right handle can be either source or target, so check both\n if (sourceNode?.type === 'splice' && params.sourceHandle === 'right' && params.source && params.sourceHandle) {\n // Try replacing as source first\n let newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n // If not found as source, try as target (right handle can be either)\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on tube fiber source handle - only one edge per handle\n if (sourceNode?.type === 'tube' && params.sourceHandle?.startsWith('fiber-') && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on tube fiber target handle - only one edge per handle\n if (targetNode?.type === 'tube' && params.targetHandle?.startsWith('fiber-') && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n if (\n (sourceNode?.type === 'cable' || sourceNode?.type === 'tube') &&\n params.sourceHandle?.startsWith('tube-') &&\n params.source &&\n params.sourceHandle\n ) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n if (\n (targetNode?.type === 'cable' || targetNode?.type === 'tube') &&\n params.targetHandle?.startsWith('tube-') &&\n params.target &&\n params.targetHandle\n ) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Replace existing edge on cable button handle connections - only one edge per handle\n if (isButtonHandleConnection && params.source && params.sourceHandle && params.target && params.targetHandle) {\n // Get cable color from source node\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const cableColor = sourceNodeData?.color || (sourceNodeData?.tubeStartIndex ? baseColorFor(sourceNodeData.tubeStartIndex) : '#6366f1');\n // Try replacing as source first\n let newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'source',\n data: { color: cableColor },\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n // Try replacing as target\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'target',\n data: { color: cableColor },\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Try to replace existing edge on target for PDU power connections\n if (isPduSource && looksLikePowerTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n // Allow replacing existing network edge on target when connecting from switch (like power PDU behavior)\n if (isSwitchSource && looksLikeNetworkTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n\n const validation = localStore.validateConnection({\n source: params.source ?? null,\n target: params.target ?? null,\n sourceHandle: params.sourceHandle ?? null,\n targetHandle: params.targetHandle ?? null,\n });\n if (!validation.valid) {\n // If allowReconnectExisting is enabled, try to replace existing edge from either end\n if (allowReconnectExisting) {\n // Try replacing from source handle\n if (params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n // Try replacing from target handle\n if (params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n }\n \n // Try to replace existing edge on source for PDU connections (legacy behavior)\n if (isPduSource && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: looksLikePowerTarget ? 'power' : 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n // Allow replacing existing network edge on source when connecting from switch (like power PDU behavior)\n if (isSwitchSource && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: params,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n setEdges(newEdges);\n return;\n }\n }\n if (debug) {\n console.warn(`Connection rejected: ${validation.reason}`);\n }\n return;\n }\n\n const edgeToAdd = {\n ...params,\n type: edgeType,\n zIndex: selectEdgeZIndex({ ...params, id: 'temp-id' } as NetworkEdge),\n data: edgeData,\n } as Connection;\n\n setEdges((eds) => {\n const newEdges = addEdge(edgeToAdd, eds);\n // Find the newly added edge and animate it\n const newEdge = newEdges[newEdges.length - 1];\n if (newEdge) {\n setAnimatingEdges((prev) => new Set(prev).add(newEdge.id));\n // Remove animation class after animation completes\n setTimeout(() => {\n setAnimatingEdges((prev) => {\n const next = new Set(prev);\n next.delete(newEdge.id);\n return next;\n });\n }, 1000); // Animation duration matches CSS\n }\n return newEdges;\n });\n },\n [setEdges, localStore, selectEdgeZIndex, getNodeById, debug, deriveFiberColorFromSource, allowReconnectExisting, useSmoothstepEdgesForTubes]\n );\n\n // Handle edge updates (when user drags an edge endpoint to reconnect)\n const onEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (!newConnection.source || !newConnection.target || !newConnection.sourceHandle || !newConnection.targetHandle) {\n return;\n }\n\n // Prevent reconnection that would disconnect tube handles\n const oldSourceHandle = oldEdge.sourceHandle || '';\n const oldTargetHandle = oldEdge.targetHandle || '';\n const newSourceHandle = newConnection.sourceHandle || '';\n const newTargetHandle = newConnection.targetHandle || '';\n \n // If old edge has a tube handle on source, new connection must keep the same tube handle\n if (oldSourceHandle.startsWith('tube-') && newSourceHandle !== oldSourceHandle) {\n if (debug) {\n console.log('Edge update blocked: Cannot disconnect tube handle', { oldEdge, newConnection });\n }\n return; // Prevent the update\n }\n \n // If old edge has a tube handle on target, new connection must keep the same tube handle\n if (oldTargetHandle.startsWith('tube-') && newTargetHandle !== oldTargetHandle) {\n if (debug) {\n console.log('Edge update blocked: Cannot disconnect tube handle', { oldEdge, newConnection });\n }\n return; // Prevent the update\n }\n\n const sourceNode = getNodeById(newConnection.source);\n const targetNode = getNodeById(newConnection.target);\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const looksLikePowerTarget = !!newConnection.targetHandle && (newConnection.targetHandle.startsWith('pwr') || newConnection.targetHandle.startsWith('power'));\n const isTubeToCable = sourceNode?.type === 'tube' && targetNode?.type === 'cable';\n const isCableToTube = sourceNode?.type === 'cable' && targetNode?.type === 'tube';\n const isTubeConnection = isTubeToCable || isCableToTube;\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';\n if (isPduSource && looksLikePowerTarget) {\n edgeType = 'power';\n } else if (isTubeConnection) {\n edgeType = useSmoothstepEdgesForTubes ? 'smoothstep' : 'fiber';\n } else {\n edgeType = 'fiber';\n }\n\n // Derive fiber color from new source node handle\n let edgeData: { color?: string; striped?: boolean } | undefined;\n if ((edgeType === 'fiber' || edgeType === 'smoothstep') && !isPduSource) {\n const colorInfo = deriveFiberColorFromSource(newConnection.source, newConnection.sourceHandle);\n if (colorInfo) {\n edgeData = { color: colorInfo.color, striped: colorInfo.striped };\n }\n }\n\n // Update the edge with new connection and recalculated data\n setEdges((eds) => {\n const updated = eds.map((e) => {\n if (e.id === oldEdge.id) {\n return {\n ...e,\n source: newConnection.source!,\n target: newConnection.target!,\n sourceHandle: newConnection.sourceHandle,\n targetHandle: newConnection.targetHandle,\n type: edgeType,\n data: edgeData !== undefined ? { ...e.data, ...edgeData } : e.data,\n zIndex: selectEdgeZIndex({ ...newConnection, id: e.id, type: edgeType } as NetworkEdge),\n style: { ...e.style, zIndex: selectEdgeZIndex({ ...newConnection, id: e.id, type: edgeType } as NetworkEdge) },\n };\n }\n return e;\n });\n return updated;\n });\n },\n [setEdges, getNodeById, deriveFiberColorFromSource, selectEdgeZIndex, useSmoothstepEdgesForTubes, debug]\n );\n\n const handleNodeClick = useCallback(\n (event: React.MouseEvent, node: Node) => {\n const isCommandClick = event.metaKey || event.ctrlKey;\n\n // If a tube is clicked and it has a parent cable, select the parent instead\n if (node.type === 'tube' && node.parentId && !isCommandClick) {\n const allNodes = getNodes();\n const parentNode = allNodes.find(n => n.id === node.parentId && n.type === 'cable');\n if (parentNode) {\n // Select the parent cable in React Flow\n setNodes((nds) => nds.map((n) => ({ ...n, selected: n.id === parentNode.id })));\n if (onNodeClick) {\n onNodeClick(parentNode as NetworkNode);\n }\n return;\n }\n }\n\n if (isCommandClick && node.type === 'device') {\n const data = node.data || {};\n const currentView: 'front' | 'rear' = data.view || (Array.isArray(data.rearPorts) && data.rearPorts.length > 0 ? 'rear' : 'front');\n const nextView: 'front' | 'rear' = currentView === 'front' ? 'rear' : 'front';\n\n if (debug) {\n console.log(`Command+click: Toggling device ${node.id} from ${currentView} to ${nextView}`);\n }\n\n // Use external onViewChange instead of internal state management\n if (onViewChange) {\n onViewChange(node.id, nextView);\n }\n\n onNodeClick && onNodeClick(node as NetworkNode);\n } else {\n // Allow regular clicks on all nodes (including devices) to trigger selection\n // React Flow will handle the selection, and useOnSelectionChange will call onNodeClick\n onNodeClick && onNodeClick(node as NetworkNode);\n }\n },\n [onViewChange, onNodeClick, debug, getNodes, setNodes]\n );\n\n // Double-click no longer removes edges to avoid accidental disconnects during interactions\n const handleNodeDoubleClick = useCallback(() => {}, []);\n\n const handleEdgeClick = useCallback(\n (event: React.MouseEvent, edge: Edge) => {\n if (onEdgeClick) {\n onEdgeClick(edge as NetworkEdge);\n }\n },\n [onEdgeClick]\n );\n\n // Track selection to show a toggle UI\n const [selectedNode, setSelectedNode] = useState<Node | null>(null);\n const [animatingEdges, setAnimatingEdges] = useState<Set<string>>(new Set());\n \n useOnSelectionChange({\n onChange: ({ nodes }) => {\n if (nodes && nodes.length === 1) {\n const node = nodes[0];\n // If a tube is selected and it has a parent, select the parent cable instead\n if (node.type === 'tube' && node.parentId) {\n const allNodes = getNodes();\n const parentNode = allNodes.find(n => n.id === node.parentId && n.type === 'cable');\n if (parentNode) {\n setSelectedNode(parentNode);\n // Select the parent cable in React Flow\n setNodes((nds) => nds.map((n) => ({ ...n, selected: n.id === parentNode.id })));\n if (onNodeClick) {\n onNodeClick(parentNode as NetworkNode);\n }\n return;\n }\n }\n setSelectedNode(node);\n // Also call onNodeClick when a node is selected via React Flow selection\n // This ensures device nodes can be selected even if regular clicks don't trigger onNodeClick\n if (onNodeClick) {\n onNodeClick(node as NetworkNode);\n }\n } else {\n setSelectedNode(null);\n // Clear selection in parent when no nodes are selected\n if (onNodeClick) {\n onNodeClick(null);\n }\n }\n },\n });\n\n // Handle connection start - track when user starts connecting\n const handleConnectStart = useCallback(\n (_event: React.MouseEvent | React.TouchEvent, { nodeId, handleType }: { nodeId: string | null; handleType: string | null }) => {\n if (debug) {\n console.log('Connection started from', { nodeId, handleType });\n }\n },\n [debug]\n );\n\n // Handle connection end - animate the newly created edge\n const handleConnectEnd = useCallback(\n (event: MouseEvent | TouchEvent) => {\n // The edge will be added via onConnect, so we'll track it there\n if (debug) {\n console.log('Connection ended', event);\n }\n },\n [debug]\n );\n\n const toggleSelectedFace = useCallback(() => {\n if (!selectedNode) return;\n const node = getNodeById(selectedNode.id);\n if (!node) return;\n\n if (node.type === 'rack') {\n const nodeData = (node.data as NetworkNode['data']) || {};\n const currentFace: 'front' | 'rear' = (nodeData.face as 'front' | 'rear') || 'front';\n const next: 'front' | 'rear' = currentFace === 'front' ? 'rear' : 'front';\n if (onRackFaceChange) {\n onRackFaceChange(node.id, next);\n // Also propagate to child devices via onViewChange if provided\n if (onViewChange) {\n const childNodes = getNodes().filter(n => n.parentId === node.id);\n childNodes.forEach(child => {\n onViewChange(child.id, next);\n });\n }\n } else {\n // Fallback: update rack face and propagate to child devices' view\n setNodes((nodes) => nodes.map(n => {\n if (n.id === node.id) {\n return { ...n, data: { ...n.data, face: next } } as Node;\n }\n if (n.parentId === node.id) {\n return { ...n, data: { ...n.data, view: next } } as Node;\n }\n return n;\n }));\n }\n return;\n }\n\n if (node.type === 'device') {\n const nodeData = (node.data as NetworkNode['data']) || {};\n const hasRear = Array.isArray(nodeData.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData.ports) && nodeData.ports.length > 0;\n const currentView: 'front' | 'rear' = (nodeData.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n const next: 'front' | 'rear' = currentView === 'front' ? 'rear' : 'front';\n if (onViewChange) {\n onViewChange(node.id, next);\n } else {\n setNodes((nodes) => nodes.map(n => n.id === node.id ? ({ ...n, data: { ...n.data, view: next } } as Node) : n));\n }\n }\n }, [selectedNode, getNodeById, onRackFaceChange, onViewChange, setNodes, getNodes]);\n\n // Add animation class and apply rear/front visibility rules\n const edgesWithAnimation = useMemo(() => {\n return reactFlowEdges.map(edge => {\n const e = edge as unknown as NetworkEdge;\n // Resolve endpoints\n const sourceNode = getNodeById(String(e.source)) as unknown as Node | undefined;\n const targetNode = getNodeById(String(e.target)) as unknown as Node | undefined;\n // Determine handle sides\n const sourceSide = getHandleSide((e.sourceHandle || '') as string, sourceNode as unknown as NetworkNode);\n const targetSide = getHandleSide((e.targetHandle || '') as string, targetNode as unknown as NetworkNode);\n // Determine endpoint views\n const sourceView = (sourceNode && (sourceNode as unknown as NetworkNode).data?.view) as 'front' | 'rear' | undefined;\n const targetView = (targetNode && (targetNode as unknown as NetworkNode).data?.view) as 'front' | 'rear' | undefined;\n const sourceIsRear = sourceNode?.type === 'device' && sourceView === 'rear';\n const targetIsRear = targetNode?.type === 'device' && targetView === 'rear';\n // Hide when both endpoints that are in rear view do not use rear handles\n const hideForSource = sourceIsRear && sourceSide !== 'rear';\n const hideForTarget = targetIsRear && targetSide !== 'rear';\n const shouldHide = hideForSource && hideForTarget;\n // Compose styles\n const nextStyle: React.CSSProperties | undefined = shouldHide\n ? { ...edge.style, opacity: 0, pointerEvents: 'none' as const, zIndex: 0 }\n : edge.style;\n return {\n ...edge,\n style: nextStyle,\n className: animatingEdges.has(edge.id) ? 'edge-connecting' : edge.className,\n };\n });\n }, [reactFlowEdges, animatingEdges, getNodeById]);\n\n return (\n <div ref={reactFlowWrapper} className={`${className || ''} ${colorMode === 'light' ? 'react-flow-light' : 'react-flow-dark'}`} style={{ width: '100%', height: '100%', ...style }}>\n <ReactFlow\n nodes={reactFlowNodes}\n edges={edgesWithAnimation}\n onNodesChange={(changes) => {\n handleNodesChange(changes);\n if (!isControlled) {\n localStore.setState({ nodes: latestNodesRef.current as NetworkNode[] });\n } else {\n externalOnNodesChange && externalOnNodesChange(latestNodesRef.current as NetworkNode[]);\n }\n }}\n onEdgesChange={(changes) => {\n // Filter out deletions of edges connected to tube handles (tube-* handles)\n const filteredChanges = changes.filter((change) => {\n if (change.type === 'remove') {\n // Find the edge being removed\n const edgeToRemove = latestEdgesRef.current.find((e) => e.id === change.id);\n if (edgeToRemove) {\n // Check if either handle is a tube handle (tube-*)\n const sourceHandle = edgeToRemove.sourceHandle || '';\n const targetHandle = edgeToRemove.targetHandle || '';\n const isTubeHandle = sourceHandle.startsWith('tube-') || targetHandle.startsWith('tube-');\n \n if (isTubeHandle) {\n if (debug) {\n console.log('Edge deletion blocked: Edge connected to tube handle is not detachable', edgeToRemove);\n }\n return false; // Filter out this deletion\n }\n }\n }\n return true; // Allow all other changes\n });\n \n // Only process changes if there are any after filtering\n if (filteredChanges.length > 0) {\n onEdgesChange(filteredChanges);\n if (!isControlled) {\n localStore.setState({ edges: latestEdgesRef.current as NetworkEdge[] });\n } else {\n externalOnEdgesChange && externalOnEdgesChange(latestEdgesRef.current as NetworkEdge[]);\n }\n }\n }}\n onConnect={onConnect}\n onConnectStart={handleConnectStart}\n onConnectEnd={handleConnectEnd}\n onEdgeUpdate={onEdgeUpdate}\n isValidConnection={isValidConnection}\n onNodeClick={handleNodeClick}\n onNodeDoubleClick={handleNodeDoubleClick}\n onNodeDragStart={handleNodeDragStart}\n onNodeDrag={handleNodeDrag}\n onNodeDragStop={handleNodeDragStop}\n onEdgeClick={handleEdgeClick}\n onInit={onInit}\n nodeTypes={memoizedNodeTypes}\n edgeTypes={memoizedEdgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: true\n }}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\n selectNodesOnDrag={false}\n fitView\n proOptions={{ hideAttribution: true }}\n >\n <Background color={colorMode === 'light' ? '#e5e5e5' : '#2a2a2a'} />\n <Controls />\n <MiniMap />\n <Panel position=\"bottom-right\" className=\"react-networks-attribution\">\n <a\n href=\"https://github.com/MP70/react-networks\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"react-networks-attribution-link\"\n >\n react-networks\n </a>\n </Panel>\n </ReactFlow>\n {showDownloadButton && (\n <button\n className=\"download-button\"\n onClick={onDownload}\n style={{\n position: 'absolute',\n top: downloadButtonPosition.includes('top') ? '10px' : 'auto',\n bottom: downloadButtonPosition.includes('bottom') ? '10px' : 'auto',\n right: downloadButtonPosition.includes('right') ? '10px' : 'auto',\n left: downloadButtonPosition.includes('left') ? '10px' : 'auto',\n zIndex: 1000,\n background: '#374151',\n color: '#e5e7eb',\n border: '1px solid #4b5563',\n borderRadius: '4px',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n ...downloadButtonStyle,\n }}\n >\n {downloadButtonText}\n </button>\n )}\n {selectedNode && (selectedNode.type === 'rack' || selectedNode.type === 'device') && (\n <div\n style={{\n position: 'absolute',\n top: 12,\n right: 12,\n display: 'flex',\n gap: 8,\n zIndex: 2000,\n }}\n >\n <button\n onClick={(e) => { e.preventDefault(); toggleSelectedFace(); }}\n style={{\n background: '#374151',\n color: '#e5e7eb',\n border: '1px solid #4b5563',\n borderRadius: 4,\n padding: '6px 10px',\n fontSize: 11,\n fontFamily: 'monospace',\n cursor: 'pointer',\n }}\n title={(() => {\n const nodeData = selectedNode.data as NetworkNode['data'];\n if (selectedNode.type === 'rack') {\n const face = (nodeData?.face as 'front' | 'rear') || 'front';\n return face === 'front' ? 'Switch to rear' : 'Switch to front';\n } else {\n const hasRear = Array.isArray(nodeData?.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData?.ports) && nodeData.ports.length > 0;\n const view = (nodeData?.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n return view === 'front' ? 'Switch to rear' : 'Switch to front';\n }\n })()}\n >\n {(() => {\n const nodeData = selectedNode.data as NetworkNode['data'];\n if (selectedNode.type === 'rack') {\n const face = (nodeData?.face as 'front' | 'rear') || 'front';\n return face === 'front' ? '⇄ Rear' : '⇄ Front';\n } else {\n const hasRear = Array.isArray(nodeData?.rearPorts) && nodeData.rearPorts.length > 0;\n const hasFront = Array.isArray(nodeData?.ports) && nodeData.ports.length > 0;\n const view = (nodeData?.view as 'front' | 'rear') || (hasRear && !hasFront ? 'rear' : 'front');\n return view === 'front' ? '⇄ Rear' : '⇄ Front';\n }\n })()}\n </button>\n </div>\n )}\n </div>\n );\n};\n\nexport const NetworkDiagram: React.FC<NetworkDiagramProps> = (props) => {\n return (\n <ReactFlowProvider>\n <NetworkDiagramInner {...props} />\n </ReactFlowProvider>\n );\n};\n","import { NetworkNode, NetworkEdge } from '../types';\n\ninterface InventoryRackDTO {\n id: string | number;\n name: string;\n status?: { value?: string } | string;\n u_height?: number;\n units?: number;\n facility_id?: string | number;\n serial?: string;\n asset_tag?: string;\n site?: { name?: string } | string;\n role?: { name?: string } | string;\n tenant?: { name?: string } | string;\n}\n\ninterface InventoryDeviceDTO {\n id: string | number;\n name: string;\n status?: { value?: string } | string;\n device_type?: { u_height?: number; model?: string; manufacturer?: { name?: string } };\n model?: string;\n manufacturer?: string;\n device_role?: { name?: string } | string;\n u_height?: number;\n position?: number;\n face?: 'front' | 'rear';\n rack?: { id?: string | number; name?: string } | string | number;\n primary_ip4?: { address?: string } | string;\n primary_ip6?: { address?: string } | string;\n site?: { name?: string } | string;\n}\n\ninterface InventoryCableDTO {\n id: string | number;\n type?: { label?: string };\n bandwidth?: string;\n length?: number;\n color?: string;\n status?: { value?: string } | string;\n termination_a?: { device?: { id?: string | number } | string | number; name?: string } | string;\n termination_b?: { device?: { id?: string | number } | string | number; name?: string } | string;\n}\n\n/**\n * Convert inventory rack data to NetworkNode\n */\nexport const inventoryRackToNetworkNode = (rack: InventoryRackDTO): NetworkNode => {\n return {\n id: `rack-${rack.id}`,\n type: 'rack',\n position: { x: 0, y: 0 },\n data: {\n label: rack.name,\n status: ((typeof rack.status === 'object' && rack.status) ? (rack.status as { value?: string }).value : rack.status) as 'active' | 'inactive' | 'maintenance',\n uHeight: rack.u_height ?? rack.units ?? 42,\n inventoryId: rack.id,\n inventoryType: 'rack',\n facilityId: rack.facility_id,\n serial: rack.serial,\n assetTag: rack.asset_tag,\n site: (typeof rack.site === 'object' && rack.site) ? (rack.site as { name?: string }).name : rack.site,\n role: (typeof rack.role === 'object' && rack.role) ? (rack.role as { name?: string }).name : rack.role,\n tenant: (typeof rack.tenant === 'object' && rack.tenant) ? (rack.tenant as { name?: string }).name : rack.tenant,\n },\n };\n};\n\n/**\n * Convert inventory device data to NetworkNode\n */\nexport const inventoryDeviceToNetworkNode = (device: InventoryDeviceDTO): NetworkNode => {\n return {\n id: `device-${device.id}`,\n type: 'device',\n position: { x: 0, y: 0 },\n parentId: device.rack ? `rack-${(typeof device.rack === 'object' && device.rack ? (device.rack as { id?: string | number }).id : device.rack)}` : undefined,\n extent: device.rack ? 'parent' : undefined,\n data: {\n label: device.name,\n status: ((typeof device.status === 'object' && device.status) ? (device.status as { value?: string }).value : device.status) as 'active' | 'inactive' | 'maintenance',\n deviceType: device.device_type?.model ?? device.model,\n manufacturer: (device.device_type?.manufacturer?.name ?? device.manufacturer),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n role: (typeof device.device_role === 'object' && device.device_role) ? (device.device_role as { name?: string }).name : (device as any).role,\n uHeight: device.device_type?.u_height ?? device.u_height ?? 1,\n uPosition: device.position || 1,\n view: (device.face as 'front' | 'rear') || 'front',\n inventoryId: device.id,\n inventoryType: 'device',\n primaryIp4: (typeof device.primary_ip4 === 'object' && device.primary_ip4) ? (device.primary_ip4 as { address?: string }).address : device.primary_ip4,\n primaryIp6: (typeof device.primary_ip6 === 'object' && device.primary_ip6) ? (device.primary_ip6 as { address?: string }).address : device.primary_ip6,\n site: (typeof device.site === 'object' && device.site) ? (device.site as { name?: string }).name : device.site,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n rack: (typeof device.rack === 'object' && device.rack) ? (device.rack as { name?: string }).name : (device.rack as any),\n },\n };\n};\n\n/**\n * Convert inventory cable data to NetworkEdge\n */\nexport const inventoryCableToNetworkEdge = (cable: InventoryCableDTO): NetworkEdge => {\n const getDeviceId = (term: InventoryCableDTO['termination_a']) => {\n if (!term) return undefined;\n if (typeof term === 'string') return term;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const dev = (term as any).device;\n if (typeof dev === 'object' && dev) return (dev as { id?: string | number }).id;\n return dev as string | number | undefined;\n };\n const termADeviceId = getDeviceId(cable.termination_a);\n const termBDeviceId = getDeviceId(cable.termination_b);\n return {\n id: `cable-${cable.id}`,\n source: `device-${termADeviceId}`,\n target: `device-${termBDeviceId}`,\n type: 'fiber',\n data: {\n bandwidth: cable.type?.label ?? cable.bandwidth,\n length: cable.length || 0,\n color: cable.color,\n inventoryId: cable.id,\n inventoryType: 'cable',\n status: ((typeof cable.status === 'object' && cable.status) ? (cable.status as { value?: string }).value : cable.status),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n terminationA: (typeof cable.termination_a === 'object' && cable.termination_a) ? (cable.termination_a as { name?: string }).name : (cable.termination_a as any),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n terminationB: (typeof cable.termination_b === 'object' && cable.termination_b) ? (cable.termination_b as { name?: string }).name : (cable.termination_b as any),\n },\n };\n};\n\n/**\n * Convert inventory data to network diagram format\n */\nexport const inventoryToNetworkDiagram = (data: {\n racks: InventoryRackDTO[];\n devices: InventoryDeviceDTO[];\n cables: InventoryCableDTO[];\n}): { nodes: NetworkNode[]; edges: NetworkEdge[] } => {\n const nodes: NetworkNode[] = [];\n const edges: NetworkEdge[] = [];\n\n data.racks.forEach(rack => nodes.push(inventoryRackToNetworkNode(rack)));\n data.devices.forEach(device => nodes.push(inventoryDeviceToNetworkNode(device)));\n data.cables.forEach(cable => edges.push(inventoryCableToNetworkEdge(cable)));\n\n return { nodes, edges };\n};\n\n/**\n * Generate simple layout positions for nodes array\n */\nexport const generateLayout = (nodes: NetworkNode[]): NetworkNode[] => {\n const rackNodes = nodes.filter(n => n.type === 'rack');\n const deviceNodes = nodes.filter(n => n.type === 'device');\n const otherNodes = nodes.filter(n => !['rack', 'device'].includes(n.type));\n\n rackNodes.forEach((rack, index) => {\n rack.position = { x: index * 300, y: 100 };\n });\n\n deviceNodes.forEach(device => {\n if (device.parentId) {\n const parentRack = rackNodes.find(r => r.id === device.parentId);\n if (parentRack) {\n const uPosition = device.data.uPosition || 1;\n const uHeight = device.data.uHeight || 1;\n device.position = {\n x: parentRack.position.x + 50,\n y: parentRack.position.y + (uPosition * 20) - (uHeight * 10),\n };\n }\n } else {\n device.position = { x: Math.random() * 400 + 100, y: Math.random() * 200 + 50 };\n }\n });\n\n otherNodes.forEach((node, index) => {\n node.position = { x: index * 150 + 100, y: 300 };\n });\n\n return nodes;\n};\n\n\n","import { NetworkNode, RackConfig, RackDevice, Width } from '../types';\nimport { calculateDevicePositionFromU, findNextAvailableUPosition } from './u-positioning';\n\n/**\n * Configuration options for building nodes from rack schema\n */\nexport interface RackSchemaOptions {\n /** How to handle device placement conflicts */\n conflictPolicy?: 'strict' | 'nearest';\n /** Whether to validate all placements before creating nodes */\n validatePlacements?: boolean;\n /** Custom device type mapping from schema to NetworkNode type */\n deviceTypeMapping?: Record<string, NetworkNode['type']>;\n}\n\n/**\n * Error thrown when device placement conflicts occur in strict mode\n */\nexport class DevicePlacementError extends Error {\n constructor(\n public rackId: string,\n public deviceId: string,\n public uPosition: number,\n public uHeight: number,\n public conflictWith?: string\n ) {\n super(\n `Device placement conflict: ${deviceId} at U${uPosition}-${uPosition + uHeight - 1} in rack ${rackId}${\n conflictWith ? ` conflicts with ${conflictWith}` : ''\n }`\n );\n this.name = 'DevicePlacementError';\n }\n}\n\n/**\n * Validation result for device placement\n */\nexport interface DevicePlacementValidation {\n isValid: boolean;\n conflicts: Array<{\n deviceId: string;\n uPosition: number;\n uHeight: number;\n conflictWith: string;\n }>;\n outOfBounds: Array<{\n deviceId: string;\n uPosition: number;\n uHeight: number;\n rackUHeight: number;\n }>;\n}\n\n/**\n * Validate device placements within a rack schema\n */\nexport function validateRackDevicePlacements(\n rack: RackConfig,\n _options: RackSchemaOptions = {}\n): DevicePlacementValidation {\n const conflicts: DevicePlacementValidation['conflicts'] = [];\n const outOfBounds: DevicePlacementValidation['outOfBounds'] = [];\n \n // Check for out-of-bounds placements\n for (const device of rack.devices) {\n const deviceEnd = device.unit + device.height - 1;\n if (deviceEnd > rack.units) {\n outOfBounds.push({\n deviceId: device.id,\n uPosition: device.unit,\n uHeight: device.height,\n rackUHeight: rack.units,\n });\n }\n }\n \n // Check for device-to-device conflicts\n for (let i = 0; i < rack.devices.length; i++) {\n const deviceA = rack.devices[i];\n const deviceAStart = deviceA.unit;\n const deviceAEnd = deviceA.unit + deviceA.height - 1;\n \n for (let j = i + 1; j < rack.devices.length; j++) {\n const deviceB = rack.devices[j];\n const deviceBStart = deviceB.unit;\n const deviceBEnd = deviceB.unit + deviceB.height - 1;\n \n // Check for overlap using 1a rule (start to start+height-1)\n if (deviceAStart <= deviceBEnd && deviceAEnd >= deviceBStart) {\n conflicts.push({\n deviceId: deviceA.id,\n uPosition: deviceA.unit,\n uHeight: deviceA.height,\n conflictWith: deviceB.id,\n });\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n\n/**\n * Convert a RackDevice to NetworkNode with proper U positioning\n */\nfunction createDeviceNode(\n device: RackDevice,\n rack: NetworkNode,\n options: RackSchemaOptions = {}\n): NetworkNode {\n const { deviceTypeMapping = {} } = options;\n \n // Map device type to NetworkNode type\n const nodeType = deviceTypeMapping[device.type] || 'device';\n \n // Calculate pixel position from U position\n const position = calculateDevicePositionFromU(rack, device.unit, device.height);\n \n \n return {\n id: device.id,\n type: nodeType,\n position,\n parentId: rack.id,\n extent: 'parent',\n data: {\n label: device.name,\n status: 'active', // Default status\n deviceType: device.type,\n uHeight: device.height,\n uPosition: device.unit,\n width: device.width || Width.FULL,\n // view is controlled at node-level; default computed in DeviceNode when absent\n role: device.role, // Pass through the role property\n ports: device.ports,\n rearPorts: device.rearPorts,\n connections: device.connections,\n },\n };\n}\n\n/**\n * Convert a RackConfig to NetworkNode\n */\nfunction createRackNode(rack: RackConfig): NetworkNode {\n return {\n id: rack.id,\n type: 'rack',\n position: rack.position,\n data: {\n label: rack.name,\n status: 'active',\n uHeight: rack.units,\n uNumberingDirection: rack.uNumberingDirection || 'bottom-up',\n customHeaderText: rack.customHeaderText,\n ports: [], // Default empty array, can be overridden\n },\n };\n}\n\n/**\n * Build NetworkNode array from RackConfig array with comprehensive validation\n */\nexport function buildNodesFromRackConfig(\n racks: RackConfig[],\n options: RackSchemaOptions = {}\n): NetworkNode[] {\n const { conflictPolicy = 'strict', validatePlacements = true } = options;\n const nodes: NetworkNode[] = [];\n const deviceNodes: NetworkNode[] = [];\n \n // Validate all racks first if requested\n if (validatePlacements) {\n for (const rack of racks) {\n const validation = validateRackDevicePlacements(rack, options);\n \n if (!validation.isValid) {\n if (conflictPolicy === 'strict') {\n // Report all conflicts and out-of-bounds\n const errors: string[] = [];\n \n validation.conflicts.forEach(conflict => {\n errors.push(\n `Device ${conflict.deviceId} at U${conflict.uPosition}-${conflict.uPosition + conflict.uHeight - 1} conflicts with ${conflict.conflictWith}`\n );\n });\n \n validation.outOfBounds.forEach(bound => {\n errors.push(\n `Device ${bound.deviceId} at U${bound.uPosition}-${bound.uPosition + bound.uHeight - 1} exceeds rack height (${bound.rackUHeight}U)`\n );\n });\n \n throw new DevicePlacementError(\n rack.id,\n validation.conflicts[0]?.deviceId || validation.outOfBounds[0]?.deviceId || 'unknown',\n validation.conflicts[0]?.uPosition || validation.outOfBounds[0]?.uPosition || 1,\n validation.conflicts[0]?.uHeight || validation.outOfBounds[0]?.uHeight || 1\n );\n }\n }\n }\n }\n \n // Create rack nodes first (required for device parent references)\n for (const rack of racks) {\n const rackNode = createRackNode(rack);\n nodes.push(rackNode);\n \n // Create device nodes for this rack\n for (const device of rack.devices) {\n try {\n const deviceNode = createDeviceNode(device, rackNode, options);\n deviceNodes.push(deviceNode);\n } catch (error) {\n if (conflictPolicy === 'strict') {\n throw error;\n } else if (conflictPolicy === 'nearest') {\n // Try to find nearest available position\n const availablePosition = findNextAvailableUPosition(\n rackNode,\n { id: device.id, type: 'device', position: { x: 0, y: 0 }, data: { label: device.name, uHeight: device.height } } as NetworkNode,\n deviceNodes,\n device.unit\n );\n \n if (availablePosition !== device.unit) {\n console.warn(\n `Device ${device.id} moved from U${device.unit} to U${availablePosition} due to conflict`\n );\n \n const adjustedDevice = { ...device, unit: availablePosition };\n const deviceNode = createDeviceNode(adjustedDevice, rackNode, options);\n deviceNodes.push(deviceNode);\n } else {\n throw new DevicePlacementError(rack.id, device.id, device.unit, device.height);\n }\n }\n }\n }\n }\n \n // Add device nodes after all rack nodes\n nodes.push(...deviceNodes);\n \n return nodes;\n}\n\n/**\n * Create a RackConfig from existing NetworkNode data (reverse operation)\n */\nexport function createRackConfigFromNodes(nodes: NetworkNode[]): RackConfig[] {\n const racks: RackConfig[] = [];\n const rackNodes = nodes.filter(node => node.type === 'rack');\n \n for (const rackNode of rackNodes) {\n const deviceNodes = nodes.filter(\n node => node.type === 'device' && node.parentId === rackNode.id\n );\n \n const devices: RackDevice[] = deviceNodes.map(deviceNode => ({\n id: deviceNode.id,\n name: deviceNode.data.label,\n unit: deviceNode.data.uPosition || 1,\n height: deviceNode.data.uHeight || 1,\n type: (deviceNode.data.deviceType as RackDevice['type']) || 'server',\n width: deviceNode.data.width,\n ports: deviceNode.data.ports,\n connections: deviceNode.data.connections,\n }));\n \n racks.push({\n id: rackNode.id,\n name: rackNode.data.label,\n position: rackNode.position,\n units: rackNode.data.uHeight || 42,\n uNumberingDirection: rackNode.data.uNumberingDirection || 'bottom-up',\n customHeaderText: rackNode.data.customHeaderText,\n devices,\n });\n }\n \n return racks;\n}\n\n/**\n * Update device U position in a rack schema\n */\nexport function updateDeviceUPosition(\n racks: RackConfig[],\n rackId: string,\n deviceId: string,\n newUPosition: number\n): RackConfig[] {\n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n return {\n ...rack,\n devices: rack.devices.map(device => {\n if (device.id !== deviceId) return device;\n return { ...device, unit: newUPosition };\n }),\n };\n });\n}\n\n/**\n * Add a device to a rack schema\n */\nexport function addDeviceToRack(\n racks: RackConfig[],\n rackId: string,\n device: RackDevice,\n options: RackSchemaOptions = {}\n): RackConfig[] {\n const { conflictPolicy = 'strict' } = options;\n \n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n // Check for conflicts if in strict mode\n if (conflictPolicy === 'strict') {\n const validation = validateRackDevicePlacements(\n { ...rack, devices: [...rack.devices, device] },\n options\n );\n \n if (!validation.isValid) {\n throw new DevicePlacementError(rackId, device.id, device.unit, device.height);\n }\n }\n \n return {\n ...rack,\n devices: [...rack.devices, device],\n };\n });\n}\n\n/**\n * Remove a device from a rack schema\n */\nexport function removeDeviceFromRack(\n racks: RackConfig[],\n rackId: string,\n deviceId: string\n): RackConfig[] {\n return racks.map(rack => {\n if (rack.id !== rackId) return rack;\n \n return {\n ...rack,\n devices: rack.devices.filter(device => device.id !== deviceId),\n };\n });\n}\n","import { NetworkNode, SpliceConfig, SpliceTrayConfig } from '../types';\nimport { calculateSplicePositionFromNumber, findNextAvailableHolderPosition, HOLDERS_PER_TRAY } from './splice-positioning';\n\n/**\n * Configuration options for building nodes from splice schema\n */\nexport interface SpliceSchemaOptions {\n /** How to handle splice placement conflicts */\n conflictPolicy?: 'strict' | 'nearest';\n /** Whether to validate all placements before creating nodes */\n validatePlacements?: boolean;\n}\n\n/**\n * Error thrown when splice placement conflicts occur in strict mode\n */\nexport class SplicePlacementError extends Error {\n constructor(\n public trayId: string,\n public spliceId: string,\n public holder: number,\n public conflictWith?: string\n ) {\n super(\n `Splice placement conflict: ${spliceId} at holder ${holder} in tray ${trayId}${\n conflictWith ? ` conflicts with ${conflictWith}` : ''\n }`\n );\n this.name = 'SplicePlacementError';\n }\n}\n\n/**\n * Validation result for splice placement\n */\nexport interface SplicePlacementValidation {\n isValid: boolean;\n conflicts: Array<{\n spliceId: string;\n holder: number;\n conflictWith: string;\n }>;\n outOfBounds: Array<{\n spliceId: string;\n holder: number;\n max: number;\n }>;\n}\n\n/**\n * Validate splice placements within a tray schema\n */\nexport function validateSplicePlacements(\n tray: SpliceTrayConfig,\n _options: SpliceSchemaOptions = {}\n): SplicePlacementValidation {\n const conflicts: SplicePlacementValidation['conflicts'] = [];\n const outOfBounds: SplicePlacementValidation['outOfBounds'] = [];\n \n // Check for out-of-bounds placements\n for (const splice of tray.splices) {\n if (splice.holder < 1 || splice.holder > HOLDERS_PER_TRAY) {\n outOfBounds.push({\n spliceId: splice.id,\n holder: splice.holder,\n max: HOLDERS_PER_TRAY,\n });\n }\n }\n \n // Check for splice-to-splice conflicts\n for (let i = 0; i < tray.splices.length; i++) {\n const spliceA = tray.splices[i];\n \n for (let j = i + 1; j < tray.splices.length; j++) {\n const spliceB = tray.splices[j];\n \n // Check if two splices are in the same holder position\n if (spliceA.holder === spliceB.holder) {\n conflicts.push({\n spliceId: spliceA.id,\n holder: spliceA.holder,\n conflictWith: spliceB.id,\n });\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n\n/**\n * Convert a SpliceConfig to NetworkNode with proper holder positioning\n */\nfunction createSpliceNode(\n splice: SpliceConfig,\n tray: NetworkNode\n): NetworkNode {\n // Calculate pixel position from holder position\n const position = calculateSplicePositionFromNumber(tray, splice.holder);\n \n return {\n id: splice.id,\n type: 'splice',\n position,\n parentId: tray.id,\n extent: 'parent',\n data: {\n label: splice.name,\n holderPosition: splice.holder,\n lossDb: splice.lossDb,\n },\n };\n}\n\n/**\n * Convert a SpliceTrayConfig to NetworkNode\n */\nfunction createTrayNode(tray: SpliceTrayConfig): NetworkNode {\n return {\n id: tray.id,\n type: 'splice-tray',\n position: tray.position,\n data: {\n label: tray.name,\n status: 'active',\n },\n };\n}\n\n/**\n * Build NetworkNode array from SpliceTrayConfig array with comprehensive validation\n */\nexport function buildNodesFromSpliceConfig(\n trays: SpliceTrayConfig[],\n options: SpliceSchemaOptions = {}\n): NetworkNode[] {\n const { conflictPolicy = 'strict', validatePlacements = true } = options;\n const nodes: NetworkNode[] = [];\n const spliceNodes: NetworkNode[] = [];\n \n // Validate all trays first if requested\n if (validatePlacements) {\n for (const tray of trays) {\n const validation = validateSplicePlacements(tray, options);\n \n if (!validation.isValid) {\n if (conflictPolicy === 'strict') {\n // Report all conflicts and out-of-bounds\n const errors: string[] = [];\n \n validation.conflicts.forEach(conflict => {\n errors.push(\n `Splice ${conflict.spliceId} at holder ${conflict.holder} conflicts with ${conflict.conflictWith}`\n );\n });\n \n validation.outOfBounds.forEach(bound => {\n errors.push(\n `Splice ${bound.spliceId} at holder ${bound.holder} is out of bounds (max: ${bound.max})`\n );\n });\n \n throw new SplicePlacementError(\n tray.id,\n validation.conflicts[0]?.spliceId || validation.outOfBounds[0]?.spliceId || 'unknown',\n validation.conflicts[0]?.holder || validation.outOfBounds[0]?.holder || 1\n );\n }\n }\n }\n }\n \n // Create tray nodes first (required for splice parent references)\n for (const tray of trays) {\n const trayNode = createTrayNode(tray);\n nodes.push(trayNode);\n \n // Create splice nodes for this tray\n for (const splice of tray.splices) {\n try {\n const spliceNode = createSpliceNode(splice, trayNode);\n spliceNodes.push(spliceNode);\n } catch (error) {\n if (conflictPolicy === 'strict') {\n throw error;\n } else if (conflictPolicy === 'nearest') {\n // Try to find nearest available position\n // Pass all nodes (tray + existing splices) for proper conflict detection\n const allNodesForConflictCheck = [...nodes, ...spliceNodes];\n const availablePosition = findNextAvailableHolderPosition(\n trayNode,\n { id: splice.id, type: 'splice', position: { x: 0, y: 0 }, data: { label: splice.name, holderPosition: splice.holder } } as NetworkNode,\n allNodesForConflictCheck,\n splice.holder\n );\n \n if (availablePosition !== splice.holder) {\n console.warn(\n `Splice ${splice.id} moved from holder ${splice.holder} to holder ${availablePosition} due to conflict`\n );\n \n const adjustedSplice = { ...splice, holder: availablePosition };\n const spliceNode = createSpliceNode(adjustedSplice, trayNode);\n spliceNodes.push(spliceNode);\n } else {\n throw new SplicePlacementError(tray.id, splice.id, splice.holder);\n }\n }\n }\n }\n }\n \n // Add splice nodes after all tray nodes\n nodes.push(...spliceNodes);\n \n return nodes;\n}\n\n/**\n * Create a SpliceTrayConfig from existing NetworkNode data (reverse operation)\n */\nexport function createSpliceConfigFromNodes(nodes: NetworkNode[]): SpliceTrayConfig[] {\n const trays: SpliceTrayConfig[] = [];\n const trayNodes = nodes.filter(node => node.type === 'splice-tray');\n \n for (const trayNode of trayNodes) {\n const spliceNodes = nodes.filter(\n node => node.type === 'splice' && node.parentId === trayNode.id\n );\n \n const splices: SpliceConfig[] = spliceNodes.map(spliceNode => ({\n id: spliceNode.id,\n name: spliceNode.data.label,\n holder: spliceNode.data.holderPosition || 1,\n lossDb: spliceNode.data.lossDb,\n }));\n \n trays.push({\n id: trayNode.id,\n name: trayNode.data.label,\n position: trayNode.position,\n splices,\n });\n }\n \n return trays;\n}\n\n/**\n * Update splice holder position in a splice schema\n */\nexport function updateSpliceHolderPosition(\n trays: SpliceTrayConfig[],\n trayId: string,\n spliceId: string,\n newHolder: number\n): SpliceTrayConfig[] {\n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n return {\n ...tray,\n splices: tray.splices.map(splice => {\n if (splice.id !== spliceId) return splice;\n return { ...splice, holder: newHolder };\n }),\n };\n });\n}\n\n/**\n * Add a splice to a tray schema\n */\nexport function addSpliceToTray(\n trays: SpliceTrayConfig[],\n trayId: string,\n splice: SpliceConfig,\n options: SpliceSchemaOptions = {}\n): SpliceTrayConfig[] {\n const { conflictPolicy = 'strict' } = options;\n \n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n // Check for conflicts if in strict mode\n if (conflictPolicy === 'strict') {\n const validation = validateSplicePlacements(\n { ...tray, splices: [...tray.splices, splice] },\n options\n );\n \n if (!validation.isValid) {\n throw new SplicePlacementError(trayId, splice.id, splice.holder);\n }\n }\n \n return {\n ...tray,\n splices: [...tray.splices, splice],\n };\n });\n}\n\n/**\n * Remove a splice from a tray schema\n */\nexport function removeSpliceFromTray(\n trays: SpliceTrayConfig[],\n trayId: string,\n spliceId: string\n): SpliceTrayConfig[] {\n return trays.map(tray => {\n if (tray.id !== trayId) return tray;\n \n return {\n ...tray,\n splices: tray.splices.filter(splice => splice.id !== spliceId),\n };\n });\n}\n\n"]}