@mp70/react-networks 0.1.8-alpha → 0.1.8-beta

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.
package/dist/index.js.map CHANGED
@@ -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/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","connectOnClick","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","onViewChangeStable","onRackFaceChangeStable","rackId","getDragOverRackIdStable","memoizedNodeTypes","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","parentClosure","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.js","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 /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */\n connectOnClick?: 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 and switches 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 const isPatchPanel = normalizedDeviceType === 'patch-panel';\n const isSwitch = deviceType === 'switch';\n if (isPatchPanel || isSwitch) {\n // Patch panel and switch 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 transform: 'translateX(-4px)', // Shift entire closure left by 4px\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 transform: 'translateX(4px)', // Compensate to keep header visually in place\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 connectOnClick = true,\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 wrapper functions using useCallback with empty deps\n // These functions access refs via .current, so they can be stable even when callbacks change\n const onViewChangeStable = useCallback((nodeId: string, view: 'front' | 'rear') => {\n onViewChangeRef.current?.(nodeId, view);\n }, []);\n \n const onRackFaceChangeStable = useCallback((rackId: string, face: 'front' | 'rear') => {\n onRackFaceChangeRef.current?.(rackId, face);\n }, []);\n \n const getDragOverRackIdStable = useCallback(() => dragOverRackIdRef.current, []);\n \n // Memoize nodeTypes to avoid recreating object every render (prevents node remounts)\n // Use stable callback wrappers to keep nodeTypes stable even if callbacks change\n const memoizedNodeTypes = useMemo(\n () => createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n ),\n [onViewChangeStable, onRackFaceChangeStable, getDragOverRackIdStable] // All dependencies are stable (empty deps)\n );\n \n // edgeTypes is already defined outside component as a constant, so use it directly\n // No memoization needed since it's already stable\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 // Prevent tubes and trays from being moved inside closures (they're locked in position)\n if (node && (node.type === 'tube' || node.type === 'splice-tray') && node.parentId) {\n const parentClosure = getNodeById(node.parentId);\n if (parentClosure && parentClosure.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={edgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: true\n }}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\n selectNodesOnDrag={false}\n connectOnClick={connectOnClick}\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/utils/fiber-colors.ts","../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/components/TubeNode.tsx","../src/components/CableNode.tsx","../src/components/MultiTubeCableNode.tsx","../src/components/CouplerNode.tsx","../src/utils/coupler-positioning.ts","../src/components/PatchPanelNode.tsx","../src/components/ClosureNode.tsx","../src/components/FibreSplitNode.tsx","../src/utils/connection-rules.ts","../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","rackWidthPx","effectiveWidth","getNodes","setNodes","useReactFlow","nodes","showUMarkers","setShowUMarkers","useState","toggleUNumberingDirection","newDirection","n","toggleFace","next","child","renderUPositions","positions","i","yPos","displayNumber","jsx","jsxs","e","FiberNode","Handle","Position","FIBER_COLORS_12","baseColorFor","normalizedId","isStriped","fiberSolidOrStriped","base","getFiberColor","getRibbonColors","ids","renderRibbonEdge","path","ribbonFiberIds","style","labelX","labelY","ribbonColors","numColors","stripeWidth","highlightEnabled","baseStrokeWidth","highlightWidth","highlightColor","Fragment","BaseEdge","colorInfo","index","currentStrokeWidth","c","EdgeLabelRenderer","FiberEdge","sourceX","sourceY","targetX","targetY","sourcePosition","targetPosition","_className","edgePath","getBezierPath","bandwidth","length","color","striped","isRibbon","highlight","highlightMaxWidth","baseEdgeStyle","PowerEdge","markerEnd","connectorType","baseStyle","renderRibbonSmoothStepEdge","getSmoothStepPath","SmoothStepFiberEdge","props","edgeStyle","ReactFlowSmoothStepEdge","getStepPath","_targetPosition","isHorizontalFirst","midX","midY","renderRibbonStepEdge","pathMatch","StepFiberEdge","_props","ThickCableEdge","_selected","Width","POWER_CONNECTORS","getPowerPortStyle","connector","isHighPower","width","height","cornerStyle","getConnectorConfig","isHighPowerConnector","getPDUPortType","portIndex","getDeviceConnectorType","deviceName","name","DeviceNode","deviceType","manufacturer","role","rearPorts","view","effectiveRackWidth","currentFace","handleSideMap","portBlock","port","handleId","fullWidthPx","halfWidthPx","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","_","idx","headerHeight","portSpacing","renderMgmtUnit","portType","leftPx","SpliceNode","lossDb","mode","edges","useEdges","leftEdge","rightEdgeAsSource","rightEdgeAsTarget","rightEdge","leftColor","rightColor","isRibbonMode","leftRibbonIds","rightRibbonIds","leftRibbonColors","rightRibbonColors","bothConnected","HOLDER_HEIGHT_PX_SINGLE","HOLDER_HEIGHT_PX_RIBBON","TRAY_HEADER_HEIGHT","TRAY_BOTTOM_PADDING","HOLDERS_PER_TRAY","SPLICE_WIDTH_PX","TRAY_WIDTH_PX","SPLICE_CENTER_X","snapToSplicePosition","splice","tray","holderHeight","spliceHeight","calculatedPosition","snappedPosition","isHolderPositionAvailable","findNextAvailableHolderPosition","baseOffset","pos","calculateSplicePositionFromNumber","holderPosition","calculateSplicePositionFromNumberWithData","spliceY","SpliceTrayNode","showHolderMarkers","setShowHolderMarkers","renderHolderPositions","TubeNode","fibersPerTube","tubeIndex","startOn","isRibbonTube","tubeConnectionHandleId","connectedTubeEdge","connectedTubeColor","defaultTubeBorderColor","tubeBorderColor","fibers","handleSize","handleSpacing","padding","borderWidth","totalHandlesWidth","tubeConnectionPosition","isSideHandle","tubeHandleWidth","tubeHandleHeight","sideInsetShadow","tubeHandleBackground","connectionHandleStyle","fiberHandles","useMemo","innerWidth","startLeft","reverseColors","fiberIdx","fiberStyle","baseColor","fiberHandleId","connectedEdge","edgeColor","left","top","React","CableNode","providedFiberCount","cableId","rotation","containerRef","rotationDegrees","innerPaddingTop","primaryText","secondaryText","defaultCableColor","cableColor","borderColor","getHandlePosition","rotationDeg","normalized","handleBackground","buttonHandleId","buttonHandleSize","buttonHandleStyle","buttonHandlePosition","containerStyle","contentStyle","MultiTubeCableNode","tubeCount","rawTubeStartIndex","tubes","tubeStartIndex","handleWidth","handleHeight","totalFibers","firstTubeColor","tubeIdx","tubeStyle","tubeHandleId","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","contentWidth","sidePadding","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","trayPositions","t","avgTrayX","a","b","tube","PatchPanelNode","header","dataWidth","dataHeight","isUpdatingRef","useRef","childNodesRef","filtered","dynamicDimensions","useEffect","currentWidth","currentHeight","widthDiff","heightDiff","panelWidth","panelHeight","displayHeader","ClosureNode","closureWidth","closureHeight","semicircleRadius","FibreSplitNode","splitterType","inputCount","outputCount","inputCountNum","inputHandlesHeight","outputCountNum","outputHandlesHeight","getHandleColor","renderInputHandles","startTop","handleBaseId","renderOutputHandles","leftEdgeHeight","leftTop","leftBottom","rightTop","rightBottom","isFiberNode","isFiberConnection","sourceNode","targetNode","normalizeHandle","defaultValidateConnection","params","ctx","normalizedSourceHandle","normalizedTargetHandle","sourceHandleAlreadyConnected","targetHandleAlreadyConnected","fiberConnection","isTubeFiberHandle","isTubeHandle","isCableTubeHandle","isTubeTubeHandle","isCableHandle","isSpliceHandle","isCouplerHandle","isSplitterHandle","sourceIsRibbon","targetIsRibbon","sourceIsTubeFiber","targetIsTubeFiber","sourceIsSplice","targetIsSplice","sourceIsCoupler","targetIsCoupler","sourceIsSplitter","targetIsSplitter","sourceIsCable","targetIsCable","sourceIsCableTube","targetIsCableTube","sourceIsTubeTube","targetIsTubeTube","sourceIsTubeHandle","targetIsTubeHandle","getHandleSide","normalizedHandleId","frontBlocks","rearBlocks","block","createNetworkDiagramStore","initial","options","state","listeners","partial","l","listener","edge","deviceView","targetHandle","targetHandleLc","isPowerHandle","isStandardNetworkHandle","isCustomPortName","isNetworkHandle","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","edgeFromAddEdge","addEdge","newEdge","zIndex","edgeWithMetadata","isSpliceRibbonMode","spliceNode","NodeWithDataType","type","children","wrapperRef","setDataTypeRef","element","parent","attempts","createNodeTypes","getDragOverRackId","edgeTypes","NetworkDiagramInner","initialNodes","initialEdges","externalOnNodesChange","externalOnEdgesChange","debug","onNodeClick","onEdgeClick","className","alignRacksToBottom","colorMode","onInit","onFlowMethods","showDownloadButton","downloadButtonPosition","downloadButtonText","downloadButtonStyle","useSmoothstepEdgesForTubes","connectOnClick","panOnDrag","panOnScroll","zoomOnScroll","validateAndFilterEdges","useCallback","edgesToValidate","nodesForValidation","seenHandles","validEdges","removedEdges","isSpecialHandle","sourceHandleKey","existingSourceEdge","isSourceSpecial","targetHandleKey","existingTargetEdge","isTargetSpecial","isControlled","initialNodesForValidation","initialEdgesRaw","validatedInitialEdges","localStore","storeNodes","storeEdges","reactFlowNodes","onNodesChange","useNodesState","reactFlowEdges","setEdges","onEdgesChange","useEdgesState","reactFlowWrapper","isMobile","setIsMobile","checkMobile","toObject","setViewport","setReactFlowNodes","setReactFlowEdges","getEdges","fitView","toPng","nodeObjects","_unused","restOptions","onDownload","dataUrl","link","error","dragOverRackId","setDragOverRackId","dragOverRackIdRef","onViewChangeRef","onRackFaceChangeRef","onViewChangeStable","onRackFaceChangeStable","rackId","getDragOverRackIdStable","nodeTypesRef","latestNodesRef","latestEdgesRef","validated","rackBottoms","r","minBottom","baselineBottom","nextNodes","currentBottom","delta","nodesMapRef","map","getNodeById","deriveFiberColorFromSource","sourceNodeId","sourceHandle","normalizedHandle","inputEdges","inputColor","fiberNumStr","fiberNum","tubeNumStr","tubeNum","nodeData","edgesZIndexRef","eds","hasChanges","updated","newZIndex","updatedNodes","parentPanel","parentTray","parentRack","originalNode","handleNodesChange","changes","updatedChanges","change","updatedNode","parentClosure","snappedResult","rackNode","absoluteX","absoluteY","handleNodeDragStart","_event","handleNodeDrag","_nodes","handleNodeDragStop","relativeX","isValidConnection","onConnect","initialValidation","isPduSource","sourceNodeData","isSwitchSource","looksLikePowerTarget","looksLikeNetworkTarget","isTubeToCable","isCableToTube","isTubeConnection","isButtonHandleConnection","edgeData","isRibbonSpliceTarget","isRibbonSpliceSource","targetSpliceData","sourceSpliceData","edgesToRemove","existingSpliceEdge","newEdgeId","newEdges","validation","sourceHandleAlreadyUsed","targetHandleAlreadyUsed","isSpecialHandleForReplacement","isSourceSpecialForReplacement","isTargetSpecialForReplacement","edgeToAdd","setAnimatingEdges","prev","onEdgeUpdate","oldEdge","newConnection","matchesSource","matchesTarget","handleNodeClick","event","isCommandClick","parentNode","nds","currentView","nextView","handleNodeDoubleClick","handleEdgeClick","selectedNode","setSelectedNode","animatingEdges","useOnSelectionChange","setSelectedEdges","selectedEdges","handleKeyDown","deletableEdges","edgeIdsToDelete","handleConnectStart","handleConnectEnd","toggleSelectedFace","hasRear","hasFront","edgesWithAnimation","nodesMap","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","deviceNode","adjustedDevice","createRackConfigFromNodes","devices","addDeviceToRack","removeDeviceFromRack","SplicePlacementError","trayId","spliceId","holder","validateSplicePlacements","spliceA","spliceB","createSpliceNode","createTrayNode","buildNodesFromSpliceConfig","spliceNodes","trayNode","allNodesForConflictCheck","adjustedSplice","createSpliceConfigFromNodes","trayNodes","splices","updateSpliceHolderPosition","newHolder","addSpliceToTray","removeSpliceFromTray"],"mappings":"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","file":"index.js","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 rackWidthPx, // Optional custom width\n } = data;\n \n // Use custom width if provided, otherwise default to RACK_WIDTH_PX (300px for standard 48.26cm/19\" rack)\n const effectiveWidth = rackWidthPx || RACK_WIDTH_PX;\n \n const { getNodes, setNodes } = useReactFlow();\n const nodes = getNodes();\n // Allow showUMarkers to be controlled via data property, default to true for backward compatibility\n const [showUMarkers, setShowUMarkers] = useState(data.showUMarkers !== undefined ? data.showUMarkers : 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: `${effectiveWidth}px`, // Custom or default width\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';\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/**\n * Get color metadata for a ribbon fiber group\n * @param ids - Array of fiber IDs (6-12 fibers, each 1-24)\n * @returns Array of color metadata objects with base color and striped flag\n * @public\n */\nexport function getRibbonColors(ids: number[]): Array<{ base: string; striped: boolean }> {\n return ids.map(id => ({\n base: baseColorFor(id),\n striped: isStriped(id),\n }));\n}\n\n/**\n * Validate ribbon fiber IDs array\n * @param ids - Array of fiber IDs to validate\n * @returns Object with isValid flag and optional error message\n * @public\n */\nexport function validateRibbonFiberIds(ids: number[]): { isValid: boolean; error?: string } {\n if (!Array.isArray(ids)) {\n return { isValid: false, error: 'Ribbon fiber IDs must be an array' };\n }\n \n if (ids.length < 6 || ids.length > 12) {\n return { isValid: false, error: `Ribbon must have 6-12 fibers, got ${ids.length}` };\n }\n \n for (const id of ids) {\n if (typeof id !== 'number' || id < 1 || id > 24) {\n return { isValid: false, error: `Fiber ID must be between 1 and 24, got ${id}` };\n }\n }\n \n // Check for duplicates\n const uniqueIds = new Set(ids);\n if (uniqueIds.size !== ids.length) {\n return { isValid: false, error: 'Ribbon fiber IDs must be unique' };\n }\n \n return { isValid: true };\n}","import React from 'react';\nimport { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\nimport { getRibbonColors } from '../utils/fiber-colors';\n\n/**\n * Render a ribbon fiber edge - colors displayed side-by-side (parallel stripes)\n * Uses layered strokes with decreasing widths to create parallel color bands\n */\nfunction renderRibbonEdge(\n id: string,\n path: string,\n ribbonFiberIds: number[],\n selected: boolean,\n style: React.CSSProperties,\n labelX: number,\n labelY: number,\n data: NetworkEdge['data']\n): React.ReactElement {\n const ribbonColors = getRibbonColors(ribbonFiberIds);\n const numColors = ribbonColors.length;\n // Each stripe gets equal width - reduced for narrower edges\n const stripeWidth = selected ? 1.2 : 1.0;\n const highlightEnabled = Boolean(data?.highlight);\n const baseStrokeWidth = selected ? 2 : 1.5;\n const highlightWidth = data?.highlightWidth ?? baseStrokeWidth * 3;\n const highlightColor = data?.highlightColor ?? ribbonColors[0]?.base ?? '#22d3ee';\n \n // Draw paths from outside to inside (first color = outermost, last = innermost)\n // Each path has decreasing stroke width so inner colors show on top\n // Each visible stripe will have equal width = stripeWidth\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={path}\n style={{\n ...style,\n stroke: highlightColor,\n strokeWidth: highlightWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightWidth}px`,\n }}\n />\n )}\n {ribbonColors.map((colorInfo, index) => {\n // Calculate stroke width so each color gets equal visible width\n // Outer path: numColors * stripeWidth, inner paths decrease by stripeWidth each\n const remainingStripes = numColors - index;\n const currentStrokeWidth = remainingStripes * stripeWidth;\n \n return (\n <path\n key={`${id}-ribbon-${index}`}\n d={path}\n stroke={colorInfo.base}\n strokeWidth={currentStrokeWidth}\n fill=\"none\"\n strokeLinecap=\"butt\"\n opacity={colorInfo.striped ? 0.9 : 1}\n style={style}\n />\n );\n })}\n \n {/* Overlay striped pattern for striped fibers (13-24) */}\n {ribbonColors.some(c => c.striped) && (\n <BaseEdge\n id={`${id}-ribbon-stripe`}\n path={path}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1,\n strokeDasharray: '3 3',\n opacity: 0.4,\n }}\n />\n )}\n \n <EdgeLabelRenderer>\n {selected && data && (data.bandwidth || data.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 ${ribbonColors[0]?.base || '#00FFFF'}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {data.bandwidth && <div>{data.bandwidth}</div>}\n {data.length && <div>{data.length}m</div>}\n <div style={{ fontSize: '8px', opacity: 0.8 }}>{ribbonFiberIds.length}F</div>\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\n}\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, ribbonFiberIds, isRibbon, highlight, highlightColor, highlightWidth } = data || {};\n const highlightEnabled = Boolean(highlight);\n \n // Check if this is a ribbon edge\n const ribbonMode = isRibbon || (ribbonFiberIds && ribbonFiberIds.length >= 6 && ribbonFiberIds.length <= 12);\n\n // Render ribbon edge if in ribbon mode\n if (ribbonMode && ribbonFiberIds) {\n return renderRibbonEdge(id, edgePath, ribbonFiberIds, selected ?? false, style ?? {}, labelX, labelY, data);\n }\n\n // Traditional single-fiber edge rendering\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 baseStrokeWidth = selected ? 3 : 2;\n const highlightMaxWidth = highlightWidth ?? baseStrokeWidth * 3;\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: baseStrokeWidth,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={edgePath}\n style={{\n ...style,\n stroke: highlightColor ?? color,\n strokeWidth: highlightMaxWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightMaxWidth}px`,\n }}\n />\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, getSmoothStepPath, BaseEdge, EdgeLabelRenderer, Position } from 'reactflow';\nimport { NetworkEdge } from '../types';\nimport { getRibbonColors } from '../utils/fiber-colors';\n\n/**\n * Render a ribbon fiber edge - colors displayed side-by-side (parallel stripes)\n * Uses layered strokes with decreasing widths to create parallel color bands\n */\nfunction renderRibbonSmoothStepEdge(\n id: string,\n sourceX: number,\n sourceY: number,\n targetX: number,\n targetY: number,\n sourcePosition: Position,\n targetPosition: Position,\n ribbonFiberIds: number[],\n selected: boolean,\n style: React.CSSProperties,\n data: NetworkEdge['data']\n): React.ReactElement {\n const ribbonColors = getRibbonColors(ribbonFiberIds);\n const numColors = ribbonColors.length;\n // Each stripe gets equal width - slightly slimmer than before\n const stripeWidth = selected ? 1.8 : 1.5;\n const highlightEnabled = Boolean(data?.highlight);\n const baseStrokeWidth = selected ? 3 : 2.5;\n const highlightWidth = data?.highlightWidth ?? baseStrokeWidth * 3;\n const highlightColor = data?.highlightColor ?? ribbonColors[0]?.base ?? '#22d3ee';\n \n const [path, labelX, labelY] = getSmoothStepPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n });\n \n // Draw paths from outside to inside (first color = outermost, last = innermost)\n // Each path has decreasing stroke width so inner colors show on top\n // Each visible stripe will have equal width = stripeWidth\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={path}\n style={{\n ...style,\n stroke: highlightColor,\n strokeWidth: highlightWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightWidth}px`,\n }}\n />\n )}\n {ribbonColors.map((colorInfo, index) => {\n // Calculate stroke width so each color gets equal visible width\n // Outer path: numColors * stripeWidth, inner paths decrease by stripeWidth each\n const remainingStripes = numColors - index;\n const currentStrokeWidth = remainingStripes * stripeWidth;\n \n return (\n <path\n key={`${id}-ribbon-${index}`}\n d={path}\n stroke={colorInfo.base}\n strokeWidth={currentStrokeWidth}\n fill=\"none\"\n strokeLinecap=\"butt\"\n opacity={colorInfo.striped ? 0.9 : 1}\n style={style}\n />\n );\n })}\n \n {ribbonColors.some(c => c.striped) && (\n <BaseEdge\n id={`${id}-ribbon-stripe`}\n path={path}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1,\n strokeDasharray: '3 3',\n opacity: 0.4,\n }}\n />\n )}\n \n <EdgeLabelRenderer>\n {selected && data && (data.bandwidth || data.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 ${ribbonColors[0]?.base || '#00FFFF'}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {data.bandwidth && <div>{data.bandwidth}</div>}\n {data.length && <div>{data.length}m</div>}\n <div style={{ fontSize: '8px', opacity: 0.8 }}>{ribbonFiberIds.length}F</div>\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\n}\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 * - Supports ribbon fiber rendering\n */\nexport const SmoothStepFiberEdge: 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', ribbonFiberIds, isRibbon, highlight, highlightColor, highlightWidth } = data || {};\n const highlightEnabled = Boolean(highlight);\n\n // Check if this is a ribbon edge\n const ribbonMode = isRibbon || (ribbonFiberIds && ribbonFiberIds.length >= 6 && ribbonFiberIds.length <= 12);\n\n // Render ribbon edge if in ribbon mode\n if (ribbonMode && ribbonFiberIds) {\n return renderRibbonSmoothStepEdge(\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n ribbonFiberIds,\n selected ?? false,\n style ?? {},\n data\n );\n }\n\n // Traditional single-fiber edge rendering\n // Apply color from data to the edge style\n const baseStrokeWidth = selected ? 4 : 3;\n const highlightMaxWidth = highlightWidth ?? baseStrokeWidth * 3;\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: baseStrokeWidth,\n } as React.CSSProperties;\n\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={getSmoothStepPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n })[0]}\n style={{\n ...style,\n stroke: highlightColor ?? color,\n strokeWidth: highlightMaxWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightMaxWidth}px`,\n }}\n />\n )}\n <ReactFlowSmoothStepEdge\n {...props}\n id={id}\n sourceX={sourceX}\n sourceY={sourceY}\n targetX={targetX}\n targetY={targetY}\n sourcePosition={sourcePosition}\n targetPosition={targetPosition}\n data={data}\n selected={selected}\n style={edgeStyle}\n />\n </>\n );\n};\n\n","import React from 'react';\nimport { EdgeProps, BaseEdge, Position, EdgeLabelRenderer } from 'reactflow';\nimport { NetworkEdge } from '../types';\nimport { getRibbonColors } from '../utils/fiber-colors';\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 * Render a ribbon fiber edge - colors displayed side-by-side (parallel stripes)\n * Uses layered strokes with decreasing widths to create parallel color bands\n */\nfunction renderRibbonStepEdge(\n id: string,\n path: string,\n ribbonFiberIds: number[],\n selected: boolean,\n style: React.CSSProperties,\n data: NetworkEdge['data']\n): React.ReactElement {\n const ribbonColors = getRibbonColors(ribbonFiberIds);\n const numColors = ribbonColors.length;\n // Each stripe gets equal width - reduced for narrower edges\n const stripeWidth = selected ? 1.2 : 1.0;\n const highlightEnabled = Boolean(data?.highlight);\n const baseStrokeWidth = selected ? 2 : 1.5;\n const highlightWidth = data?.highlightWidth ?? baseStrokeWidth * 3;\n const highlightColor = data?.highlightColor ?? ribbonColors[0]?.base ?? '#22d3ee';\n \n // Calculate label position (midpoint of path)\n const pathMatch = path.match(/M\\s+([\\d.]+),([\\d.]+).*L\\s+([\\d.]+),([\\d.]+)/);\n const labelX = pathMatch ? (parseFloat(pathMatch[1]) + parseFloat(pathMatch[3])) / 2 : 0;\n const labelY = pathMatch ? (parseFloat(pathMatch[2]) + parseFloat(pathMatch[4])) / 2 : 0;\n \n // Draw paths from outside to inside (first color = outermost, last = innermost)\n // Each path has decreasing stroke width so inner colors show on top\n // Each visible stripe will have equal width = stripeWidth\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={path}\n style={{\n ...style,\n stroke: highlightColor,\n strokeWidth: highlightWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightWidth}px`,\n }}\n />\n )}\n {ribbonColors.map((colorInfo, index) => {\n // Calculate stroke width so each color gets equal visible width\n // Outer path: numColors * stripeWidth, inner paths decrease by stripeWidth each\n const remainingStripes = numColors - index;\n const currentStrokeWidth = remainingStripes * stripeWidth;\n \n return (\n <path\n key={`${id}-ribbon-${index}`}\n d={path}\n stroke={colorInfo.base}\n strokeWidth={currentStrokeWidth}\n fill=\"none\"\n strokeLinecap=\"butt\"\n opacity={colorInfo.striped ? 0.9 : 1}\n style={style}\n />\n );\n })}\n \n {ribbonColors.some(c => c.striped) && (\n <BaseEdge\n id={`${id}-ribbon-stripe`}\n path={path}\n style={{\n ...style,\n stroke: '#000',\n strokeWidth: 1,\n strokeDasharray: '3 3',\n opacity: 0.4,\n }}\n />\n )}\n \n <EdgeLabelRenderer>\n {selected && data && (data.bandwidth || data.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 ${ribbonColors[0]?.base || '#00FFFF'}`,\n pointerEvents: 'none',\n zIndex: 9999,\n }}\n >\n {data.bandwidth && <div>{data.bandwidth}</div>}\n {data.length && <div>{data.length}m</div>}\n <div style={{ fontSize: '8px', opacity: 0.8 }}>{ribbonFiberIds.length}F</div>\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\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, ribbonFiberIds, isRibbon, highlight, highlightColor, highlightWidth } = data || {};\n const highlightEnabled = Boolean(highlight);\n\n // Calculate step path\n const edgePath = getStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n // Check if this is a ribbon edge\n const ribbonMode = isRibbon || (ribbonFiberIds && ribbonFiberIds.length >= 6 && ribbonFiberIds.length <= 12);\n\n // Render ribbon edge if in ribbon mode\n if (ribbonMode && ribbonFiberIds) {\n return renderRibbonStepEdge(id, edgePath, ribbonFiberIds, selected ?? false, style ?? {}, data);\n }\n\n // Traditional single-fiber edge rendering\n // Apply color from data to the edge style\n const baseStrokeWidth = selected ? 3 : 2;\n const highlightMaxWidth = highlightWidth ?? baseStrokeWidth * 3;\n const edgeStyle = {\n ...style,\n stroke: color,\n strokeWidth: baseStrokeWidth,\n strokeDasharray: 'none',\n } as React.CSSProperties;\n\n return (\n <>\n {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={edgePath}\n style={{\n ...style,\n stroke: highlightColor ?? color,\n strokeWidth: highlightMaxWidth,\n opacity: 0.7,\n strokeDasharray: '14 10',\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightMaxWidth}px`,\n }}\n />\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: _selected,\n}) => {\n const { color = '#6366f1', label, highlight, highlightColor, highlightWidth } = data || {};\n const highlightEnabled = Boolean(highlight);\n const baseStrokeWidth = 8;\n const highlightMaxWidth = highlightWidth ?? baseStrokeWidth * 1.8;\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: baseStrokeWidth, // 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 {highlightEnabled && (\n <BaseEdge\n id={`${id}-highlight`}\n path={edgePath}\n style={{\n ...style,\n stroke: highlightColor ?? color,\n strokeWidth: highlightMaxWidth,\n opacity: 0.85,\n strokeDasharray: '18 12',\n filter: `drop-shadow(0 0 8px ${highlightColor ?? color}) drop-shadow(0 0 16px ${highlightColor ?? color})`,\n ['--rn-edge-highlight-from' as string]: `${baseStrokeWidth}px`,\n ['--rn-edge-highlight-to' as string]: `${highlightMaxWidth}px`,\n }}\n />\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 */\n/**\n * Port type enumeration\n * @public\n */\nexport type PortType = 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';\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?: PortType;\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 | 'multi-tube-cable'\n | 'coupler'\n | 'closure'\n | 'fibre-split';\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 /** Optional rack width in pixels (for rack nodes, default: 300px) */\n rackWidthPx?: 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 /** Type of fibre splitter: 'splitter' or 'WDM' (default: 'splitter') */\n splitterType?: 'splitter' | 'WDM';\n /** Number of input fibers on the left (1 or 2, default: 1) */\n inputCount?: number;\n /** Number of output fibers on the right (1-64, default: 8) */\n outputCount?: 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' | '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 /** Whether this edge represents a ribbon fiber connection */\n isRibbon?: boolean;\n /** Array of fiber IDs for ribbon mode (6-12 fibers) */\n ribbonFiberIds?: number[];\n /** Highlight edge with a pulsing stroke */\n highlight?: boolean;\n /** Override highlight color (defaults to edge color) */\n highlightColor?: string;\n /** Override highlight max stroke width */\n highlightWidth?: number;\n /** Optional tag for grouping edges in demos */\n traceTag?: string;\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 /** Optional rack width in pixels (default: 300px which represents standard 48.26cm/19\" rack) */\n rackWidthPx?: number;\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 /** Splice mode: 'single' for individual fiber, 'ribbon' for ribbon splices */\n mode?: 'single' | 'ribbon';\n /** For ribbon mode: array of fiber IDs (6-12) in the ribbon */\n ribbonFiberIds?: 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 // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getNodes: () => any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getEdges: () => any[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fitView: (options?: any) => void;\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 /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */\n useSmoothstepEdgesForTubes?: boolean;\n /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */\n connectOnClick?: boolean;\n /** Disable panning on drag. Default is false. */\n panOnDrag?: boolean;\n /** Disable panning on scroll. Default is true. */\n panOnScroll?: boolean;\n /** Disable zooming on scroll. Default is true. */\n zoomOnScroll?: 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, RACK_WIDTH_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 rackWidthPx, // Optional custom rack width from parent rack\n } = data;\n \n // Use custom rack width if provided, otherwise default to RACK_WIDTH_PX (300px)\n const effectiveRackWidth = rackWidthPx || RACK_WIDTH_PX;\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 and parent rack width\n // Full width uses effective rack width + 4px padding, half width is half of that\n const fullWidthPx = effectiveRackWidth + 4;\n const halfWidthPx = Math.floor(effectiveRackWidth / 2);\n const rackDeviceWidth = width === Width.HALF ? `${halfWidthPx}px` : `${fullWidthPx}px`;\n const rackDeviceLeft = width === Width.HALF ? `${halfWidthPx}px` : 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 and switches 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 const isPatchPanel = normalizedDeviceType === 'patch-panel';\n const isSwitch = deviceType === 'switch';\n if (isPatchPanel || isSwitch) {\n // Patch panel and switch 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';\nimport { getRibbonColors } from '../utils/fiber-colors';\n\nexport const SpliceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { lossDb, mode = 'single', ribbonFiberIds } = 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 // For ribbon mode, get colors from ribbonFiberIds or from connected edges\n const isRibbonMode = mode === 'ribbon';\n const leftRibbonIds = leftEdge?.data?.ribbonFiberIds || ribbonFiberIds;\n const rightRibbonIds = rightEdge?.data?.ribbonFiberIds || ribbonFiberIds;\n const leftRibbonColors = isRibbonMode && leftRibbonIds ? getRibbonColors(leftRibbonIds) : null;\n const rightRibbonColors = isRibbonMode && rightRibbonIds ? getRibbonColors(rightRibbonIds) : null;\n \n // Only show glow when both handles are connected\n const bothConnected = !!leftEdge && !!rightEdge;\n\n // Calculate dimensions based on mode\n // Ribbon mode needs more height to accommodate horizontal ribbon stripes\n const spliceWidth = isRibbonMode ? 85 : 69;\n const spliceHeight = isRibbonMode ? 20 : 16;\n\n return (\n <div\n className={`splice-node ${selected ? 'selected' : ''}`}\n style={{\n width: spliceWidth,\n height: spliceHeight,\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 {/* Background showing colors - ribbon mode shows vertical color bands (top-to-bottom), single mode shows split */}\n {isRibbonMode && leftRibbonColors && rightRibbonColors ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n borderRadius: 8,\n overflow: 'hidden',\n opacity: 0.75,\n pointerEvents: 'none',\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n }}\n >\n {/* Left side ribbon - vertical color bands (top-to-bottom) */}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n height: '100%',\n }}\n >\n {leftRibbonColors.map((colorInfo, index) => (\n <div\n key={`left-${index}`}\n style={{\n flex: 1,\n background: colorInfo.base,\n opacity: colorInfo.striped ? 0.9 : 1,\n }}\n />\n ))}\n </div>\n {/* Right side ribbon - vertical color bands (top-to-bottom) */}\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n height: '100%',\n }}\n >\n {rightRibbonColors.map((colorInfo, index) => (\n <div\n key={`right-${index}`}\n style={{\n flex: 1,\n background: colorInfo.base,\n opacity: colorInfo.striped ? 0.9 : 1,\n }}\n />\n ))}\n </div>\n </div>\n ) : (\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 \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 background: 'transparent', // Ensure overlay is transparent\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 flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: isRibbonMode ? 8 : 9,\n fontFamily: 'monospace',\n pointerEvents: 'none',\n zIndex: 3,\n fontWeight: 'bold',\n gap: '2px',\n }}\n >\n <div>{`${lossDb.toFixed(2)} dB`}</div>\n {isRibbonMode && ribbonFiberIds && (\n <div style={{ fontSize: '7px', opacity: 0.8 }}>\n {ribbonFiberIds.length}F\n </div>\n )}\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: isRibbonMode && leftRibbonColors ? 12 : 12, // Keep width same\n height: isRibbonMode && leftRibbonColors ? 20 : 12, // Taller for ribbon mode to show vertical stripes\n borderRadius: isRibbonMode && leftRibbonColors ? '6px' : '50%', // Rounded rectangle for ribbon\n border: 'none',\n background: isRibbonMode && leftRibbonColors \n ? `linear-gradient(to bottom, ${leftRibbonColors.map(c => c.base).join(', ')})`\n : (leftColor || '#555'),\n zIndex: 100,\n cursor: 'crosshair',\n left: isRibbonMode && leftRibbonColors ? -6 : -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: isRibbonMode && rightRibbonColors ? 12 : 12, // Keep width same\n height: isRibbonMode && rightRibbonColors ? 20 : 12, // Taller for ribbon mode to show vertical stripes\n borderRadius: isRibbonMode && rightRibbonColors ? '6px' : '50%', // Rounded rectangle for ribbon\n border: 'none',\n background: isRibbonMode && rightRibbonColors\n ? `linear-gradient(to bottom, ${rightRibbonColors.map(c => c.base).join(', ')})`\n : (rightColor || '#555'),\n zIndex: 100,\n cursor: 'crosshair',\n right: isRibbonMode && rightRibbonColors ? -6 : -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: isRibbonMode && rightRibbonColors ? 12 : 12, // Keep width same\n height: isRibbonMode && rightRibbonColors ? 20 : 12, // Taller for ribbon mode to show vertical stripes\n borderRadius: isRibbonMode && rightRibbonColors ? '6px' : '50%', // Rounded rectangle for ribbon\n border: 'none',\n background: isRibbonMode && rightRibbonColors\n ? `linear-gradient(to bottom, ${rightRibbonColors.map(c => c.base).join(', ')})`\n : (rightColor || '#555'),\n zIndex: 100,\n cursor: 'crosshair',\n right: isRibbonMode && rightRibbonColors ? -6 : -6,\n top: '50%',\n transform: 'translateY(-50%)',\n }}\n />\n </div>\n );\n};\n\n","import { NetworkNode } from '../types';\n\n/**\n * Height of each holder position in pixels (one splice per holder)\n * Different heights for ribbon mode (taller) vs single mode (compact)\n */\nexport const HOLDER_HEIGHT_PX_SINGLE = 20; // For single mode splices (16px height)\nexport const HOLDER_HEIGHT_PX_RIBBON = 36; // For ribbon mode splices (32px height)\n// Default to single mode for backward compatibility\nexport const HOLDER_HEIGHT_PX = HOLDER_HEIGHT_PX_SINGLE;\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 * Uses average height to work with both single and ribbon splices\n */\nexport const calculateHolderPositionFromY = (\n tray: NetworkNode,\n y: number\n): number => {\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = y - startY;\n // Use average height to work reasonably with both modes\n const avgHeight = (HOLDER_HEIGHT_PX_SINGLE + HOLDER_HEIGHT_PX_RIBBON) / 2;\n const holderPosition = Math.round(relativeY / avgHeight) + 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 // Determine if this is a ribbon splice\n const isRibbonMode = splice.data?.mode === 'ribbon';\n const holderHeight = isRibbonMode ? HOLDER_HEIGHT_PX_RIBBON : HOLDER_HEIGHT_PX_SINGLE;\n const spliceHeight = isRibbonMode ? 32 : 16;\n\n const startY = TRAY_HEADER_HEIGHT;\n const relativeY = newPosition.y - startY;\n const calculatedPosition = Math.round(relativeY / holderHeight) + 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 // Center splice vertically in holder slot\n const baseOffset = (holderHeight - spliceHeight) / 2;\n return {\n x: SPLICE_CENTER_X, // Center splice in tray\n y: startY + (availablePosition - 1) * holderHeight + baseOffset,\n holderPosition: availablePosition,\n };\n }\n }\n\n // Snap to exact holder position, center vertically in holder slot\n const baseOffset = (holderHeight - spliceHeight) / 2;\n const snappedY = startY + (snappedPosition - 1) * holderHeight + 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 * Note: This function doesn't have access to splice data, so it uses single mode spacing\n * For ribbon splices, use calculateSplicePositionFromNumberWithData instead\n */\nexport const calculateSplicePositionFromNumber = (\n tray: NetworkNode,\n holderPosition: number\n): { x: number; y: number } => {\n // Default to single mode for backward compatibility\n return calculateSplicePositionFromNumberWithData(tray, holderPosition, false);\n};\n\n/**\n * Calculate splice position based on holder number within a tray, with mode awareness\n */\nexport const calculateSplicePositionFromNumberWithData = (\n tray: NetworkNode,\n holderPosition: number,\n isRibbonMode: boolean = false\n): { x: number; y: number } => {\n const startY = TRAY_HEADER_HEIGHT;\n const holderHeight = isRibbonMode ? HOLDER_HEIGHT_PX_RIBBON : HOLDER_HEIGHT_PX_SINGLE;\n const spliceHeight = isRibbonMode ? 32 : 16;\n // Center splice vertically in holder slot\n const baseOffset = (holderHeight - spliceHeight) / 2;\n const spliceY = startY + (holderPosition - 1) * holderHeight + 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_SINGLE, HOLDER_HEIGHT_PX_RIBBON, 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 // Use single mode height for markers to show compact spacing\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_SINGLE;\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_SINGLE}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_RIBBON + TRAY_BOTTOM_PADDING}px`, // Header + holder area + bottom padding (use ribbon height to accommodate both types)\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, { useMemo } from 'react';\nimport { Handle, Position, NodeProps, useEdges, Edge } from 'reactflow';\nimport { NetworkNode, NetworkEdge } 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 const isRibbonTube = data?.mode === 'ribbon' || (data as { ribbon?: boolean } | undefined)?.ribbon === true;\n \n // Use useEdges hook to detect connected tube and update border color dynamically\n const edges = useEdges<NetworkEdge>();\n const tubeConnectionHandleId = `tube-${tubeIndex}`;\n \n // Find edge connected to this tube's tube handle (tube-* handle)\n const connectedTubeEdge = edges.find((e: Edge<NetworkEdge>) => \n (e.source === id && e.sourceHandle === tubeConnectionHandleId) ||\n (e.target === id && e.targetHandle === tubeConnectionHandleId)\n ) as NetworkEdge | undefined;\n \n // Get color from connected edge if available, otherwise use default tube color\n const connectedTubeColor = connectedTubeEdge?.data?.color;\n const defaultTubeBorderColor = baseColorFor(((tubeIndex - 1) % 12) + 1);\n // Use connected tube color if available, otherwise fall back to default\n const tubeBorderColor = connectedTubeColor || defaultTubeBorderColor;\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 tubeConnectionPosition = startOn === 'left'\n ? Position.Left\n : startOn === 'right'\n ? Position.Right\n : Position.Bottom;\n const isSideHandle = tubeConnectionPosition !== Position.Bottom;\n const tubeHandleWidth = isSideHandle ? 14 : 20;\n const tubeHandleHeight = isSideHandle ? 8 : 20;\n const sideInsetShadow = isSideHandle\n ? `inset ${tubeConnectionPosition === Position.Left ? '-4px' : '4px'} 0 0 rgba(0, 0, 0, 0.35)`\n : 'none';\n const tubeHandleBackground = connectedTubeEdge\n ? tubeBorderColor\n : isSideHandle\n ? `linear-gradient(${tubeConnectionPosition === Position.Left ? 'to right' : 'to left'}, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0)), ${tubeBorderColor}`\n : `radial-gradient(circle, ${tubeBorderColor} 40%, transparent 70%)`;\n // Show different style when connected vs not connected\n const connectionHandleStyle: React.CSSProperties & { '--fiber-bg'?: string } = {\n width: tubeHandleWidth,\n height: tubeHandleHeight,\n borderRadius: isSideHandle ? 6 : '50%',\n opacity: connectedTubeEdge ? 0.3 : 0.9, // More visible when not connected\n pointerEvents: 'auto',\n background: tubeHandleBackground,\n backgroundColor: tubeBorderColor,\n border: connectedTubeEdge ? `2px solid ${tubeBorderColor}` : `3px dashed ${tubeBorderColor}`,\n cursor: 'crosshair',\n '--fiber-bg': tubeBorderColor,\n boxShadow: connectedTubeEdge\n ? sideInsetShadow\n : `${sideInsetShadow}${sideInsetShadow !== 'none' ? ', ' : ''}0 0 8px ${tubeBorderColor}`,\n transition: 'opacity 0.2s, box-shadow 0.2s',\n ...(tubeConnectionPosition === Position.Left\n ? { left: -(tubeHandleWidth - 4) }\n : tubeConnectionPosition === Position.Right\n ? { right: -(tubeHandleWidth - 4) }\n : {}),\n };\n\n // Render handles based on startOn mode - memoized to prevent unnecessary re-renders\n const fiberHandles = useMemo(() => {\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 const fiberHandleId = `fiber-${fiberIdx}`;\n \n // Get color from connected edge if available (for overrides)\n const connectedEdge = edges.find((e: Edge<NetworkEdge>) => {\n return (e.source === id && e.sourceHandle === fiberHandleId) ||\n (e.target === id && e.targetHandle === fiberHandleId);\n }) as NetworkEdge | undefined;\n \n let edgeColor: string | null = null;\n if (connectedEdge) {\n // Check if edge has ribbon data - if so, return grey (connected to ribbon splice)\n if (connectedEdge.data?.isRibbon || (connectedEdge.data?.ribbonFiberIds && Array.isArray(connectedEdge.data.ribbonFiberIds))) {\n edgeColor = '#808080'; // Grey for ribbon connections\n } else {\n // Return color from edge data if available\n edgeColor = connectedEdge.data?.color || null;\n }\n }\n \n // Position handles on top, horizontally arranged\n const left = startLeft + (i * (handleSize + handleSpacing));\n const top = padding;\n \n // Build handle style - same as normal fibers\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 zIndex: 10,\n cursor: 'pointer',\n '--fiber-bg': edgeColor || (isRibbonTube ? '#808080' : baseColor), // Grey when ribbon tube is unconnected\n };\n \n // Use edge color if provided (overrides default), otherwise use normal fiber color\n if (edgeColor) {\n handleStyle.backgroundColor = edgeColor;\n } else {\n if (isRibbonTube) {\n handleStyle.backgroundColor = '#808080';\n } else {\n // Normal mode: use fiber color or striped pattern\n if (fiberStyle.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberStyle.backgroundImage;\n } else {\n handleStyle.backgroundColor = baseColor;\n }\n }\n }\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={edgeColor || (isRibbonTube ? '#808080' : 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={edgeColor || (isRibbonTube ? '#808080' : baseColor)}\n />\n </React.Fragment>\n );\n }\n \n return handles;\n }, [fibers, startOn, width, edges, id, handleSize, handleSpacing, padding, borderWidth, totalHandlesWidth, isRibbonTube]);\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 overflow: 'visible',\n }}\n >\n {/* Render fiber handles */}\n {fiberHandles}\n {/* Tube connection handle for cable-to-tube connections - always visible for reconnection */}\n <Handle\n id={tubeConnectionHandleId}\n type=\"target\"\n position={tubeConnectionPosition}\n isConnectable={true}\n className=\"tube-connection-handle\"\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n title={connectedTubeEdge ? 'Connected - drag to reconnect' : 'Drag to connect cable tube'}\n />\n <Handle\n id={tubeConnectionHandleId}\n type=\"source\"\n position={tubeConnectionPosition}\n isConnectable={true}\n className=\"tube-connection-handle\"\n style={connectionHandleStyle}\n data-tube-idx={tubeIndex}\n data-tube-color={tubeBorderColor}\n title={connectedTubeEdge ? 'Connected - drag to reconnect' : 'Drag to connect cable tube'}\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 * - Represents a multi-fiber cable (1-24 fibers)\n * - Each colored handle corresponds to a single fiber\n * - Displays cable summary text (fiber count + cable identifier)\n */\nexport const CableNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected }) => {\n const {\n fiberCount: providedFiberCount,\n cableId = 'CBL-002',\n label,\n color, // Cable color prop - used for border and button handle\n rotation,\n } = data || {};\n \n const containerRef = React.useRef<HTMLDivElement>(null);\n \n // Apply rotation via ref to ensure it's not overridden\n React.useEffect(() => {\n if (containerRef.current) {\n const rotationDegrees = typeof rotation === 'number' ? rotation : 0;\n containerRef.current.style.transform = `rotate(${rotationDegrees}deg)`;\n containerRef.current.style.transformOrigin = 'center center';\n }\n }, [rotation]);\n\n const fibers = Math.max(1, Math.min(24, Number(providedFiberCount) || 12));\n const handleSize = 10;\n const handleSpacing = 2;\n const padding = 6;\n const innerPaddingTop = padding + handleSize + 4;\n const height = 60;\n const width = Math.max(120, (fibers * (handleSize + handleSpacing)) + (padding * 2));\n const totalFibers = fibers;\n\n const primaryText = label ?? `${totalFibers}f Cable`;\n const secondaryText = cableId ? `Cable ID ${cableId}` : undefined;\n const defaultCableColor = baseColorFor(1);\n \n // Use provided color or fall back to default fiber color\n const cableColor = color || defaultCableColor;\n const borderColor = selected ? '#3b82f6' : cableColor;\n\n const rotationDegrees = typeof rotation === 'number' ? rotation : 0;\n\n // Calculate handle position based on rotation\n // Original position is Top, so we map rotation to the appropriate Position\n const getHandlePosition = (rotationDeg: number): Position => {\n // Normalize rotation to 0-360 range\n const normalized = ((rotationDeg % 360) + 360) % 360;\n \n // Map rotation to Position enum\n // Top: 0°, Right: 90°, Bottom: 180°, Left: 270°\n if (normalized >= 315 || normalized < 45) {\n return Position.Top;\n } else if (normalized >= 45 && normalized < 135) {\n return Position.Right;\n } else if (normalized >= 135 && normalized < 225) {\n return Position.Bottom;\n } else {\n return Position.Left;\n }\n };\n\n const renderHandles = () => {\n const handles: React.ReactElement[] = [];\n const handlePosition = getHandlePosition(rotationDegrees);\n\n for (let i = 0; i < fibers; i++) {\n const fiberIdx = i + 1;\n const fiberStyle = fiberSolidOrStriped(fiberIdx);\n const baseColor = baseColorFor(fiberIdx);\n\n const left = padding + (i * (handleSize + handleSpacing));\n const top = -(handleSize / 2);\n\n const handleBackground = fiberStyle.backgroundImage ? fiberStyle.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 (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 <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 <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 // 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 // Calculate button handle position based on rotation (opposite side of fiber handles)\n const getButtonHandlePosition = (rotationDeg: number): Position => {\n const normalized = ((rotationDeg % 360) + 360) % 360;\n // Button is on Bottom when unrotated, so map accordingly\n if (normalized >= 315 || normalized < 45) {\n return Position.Bottom;\n } else if (normalized >= 45 && normalized < 135) {\n return Position.Left;\n } else if (normalized >= 135 && normalized < 225) {\n return Position.Top;\n } else {\n return Position.Right;\n }\n };\n \n const buttonHandlePosition = getButtonHandlePosition(rotationDegrees);\n\n // Main container with rotation applied directly\n const containerStyle: React.CSSProperties & { '--rotation'?: string } = {\n width,\n height,\n position: 'relative',\n transform: `rotate(${rotationDegrees}deg)`,\n transformOrigin: 'center center',\n '--rotation': `${rotationDegrees}deg`,\n };\n\n // Content div with styling\n const contentStyle: React.CSSProperties = {\n width: '100%',\n height: '100%',\n borderRadius: 4,\n background: '#111827',\n border: `${borderWidth}px solid ${borderColor}`,\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 return (\n <div ref={containerRef} style={containerStyle}>\n <div style={contentStyle}>\n {renderHandles()}\n {/* Button handle - position depends on rotation */}\n <Handle\n id={buttonHandleId}\n type=\"source\"\n position={buttonHandlePosition}\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={buttonHandlePosition}\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\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 2,\n transform: 'translateX(2px)',\n }}\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 </div>\n </div>\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 * MultiTubeCableNode\n * - Represents a multi-tube cable (1-24 tubes)\n * - Each colored handle corresponds to a tube within the cable\n * - Displays cable summary text (fiber count + cable identifier)\n */\nexport const MultiTubeCableNode: 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 handleWidth = 14;\n const handleHeight = 10;\n const handleSpacing = 3;\n const padding = 6;\n const innerPaddingTop = padding + handleHeight + 4;\n const height = 60;\n const width = Math.max(120, (tubes * (handleWidth + 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 * (handleWidth + handleSpacing));\n const top = -(handleHeight / 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: handleWidth,\n height: handleHeight,\n borderRadius: 6,\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\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 2,\n }}\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 </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 = 9;\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: [minimal padding] [tube] [spacing] [tray] [coupler] [handle extension] [minimal padding]\n // Content is centered with minimal equal padding on both sides\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 content width: tube + spacing + tray + coupler + handle extension\n const contentWidth = tubeWidth + PANEL_TUBE_TRAY_SPACING + TRAY_WIDTH_PX + couplerWidth + handleExtension;\n // Add minimal equal padding on both sides to center content (reduced from PANEL_PADDING)\n const sidePadding = 0; // Minimal padding to make panel thinner\n width = sidePadding + contentWidth + sidePadding;\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 minimal padding on the right (handle extension extends beyond panel, not included)\n const sidePadding = 4; // Reduced from PANEL_PADDING (8px) to reduce width\n width = maxRight + sidePadding;\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 // 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 // Use ref to cache getNodes result and only recalculate when nodes change\n const childNodesRef = useRef<NetworkNode[]>([]);\n const childNodes = useMemo(() => {\n const allNodes = getNodes();\n const filtered = allNodes.filter((node) => node.parentId === id) as NetworkNode[];\n // Only update if changed\n if (filtered.length !== childNodesRef.current.length || \n filtered.some((n, i) => n.id !== childNodesRef.current[i]?.id)) {\n childNodesRef.current = filtered;\n }\n return childNodesRef.current;\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 \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 // Use ref to cache getNodes result and only recalculate when nodes change\n const childNodesRef = useRef<NetworkNode[]>([]);\n const childNodes = useMemo(() => {\n const allNodes = getNodes();\n const filtered = allNodes.filter((node) => node.parentId === id) as NetworkNode[];\n // Only update if changed\n if (filtered.length !== childNodesRef.current.length || \n filtered.some((n, i) => n.id !== childNodesRef.current[i]?.id)) {\n childNodesRef.current = filtered;\n }\n return childNodesRef.current;\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 React from 'react';\nimport { Handle, Position, NodeProps, useEdges, Edge } from 'reactflow';\nimport { NetworkNode, NetworkEdge } from '../types';\n\n/**\n * FibreSplitNode component for rendering fiber splitters and WDM devices\n * Uses a trapezoid shape pointing right (narrow input on left, wider outputs on right)\n * \n * @public\n */\nexport const FibreSplitNode: React.FC<NodeProps<NetworkNode['data']>> = ({ data, selected, id }) => {\n const { \n label, \n splitterType = 'splitter',\n inputCount = 1,\n outputCount = 8,\n } = data || {};\n const edges = useEdges<NetworkEdge>();\n \n const displayLabel = label || (splitterType === 'WDM' ? 'WDM' : 'Splitter');\n \n // Handle dimensions matching CouplerNode\n const handleSize = 9;\n const handleSpacing = 3;\n const padding = 3;\n const minWidth = 50;\n const minHeight = 30;\n \n // Input handles: 1 or 2, positioned closer together\n const inputCountNum = Math.min(Math.max(inputCount || 1, 1), 2);\n const inputHandlesHeight = (inputCountNum * handleSize) + ((inputCountNum - 1) * handleSpacing);\n \n // Output handles\n const outputCountNum = Math.min(outputCount || 8, 48);\n const outputHandlesHeight = (outputCountNum * handleSize) + ((outputCountNum - 1) * handleSpacing);\n \n // Calculate height based on outputs (larger side)\n const totalHandlesHeight = Math.max(inputHandlesHeight, outputHandlesHeight);\n const height = Math.max(minHeight, totalHandlesHeight + (padding * 2));\n const width = Math.max(minWidth, 50);\n \n // Get color from connected edge for a handle\n const getHandleColor = (handleId: string): string => {\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 input handles on the left - 1 or 2, closer together\n const renderInputHandles = () => {\n const handles: React.ReactElement[] = [];\n const startTop = padding + (height - inputHandlesHeight) / 2;\n \n for (let i = 0; i < inputCountNum; i++) {\n const handleBaseId = `input-${i + 1}`;\n const top = startTop + (i * (handleSize + handleSpacing));\n const portColor = getHandleColor(handleBaseId);\n \n const handleStyle: React.CSSProperties = {\n position: 'absolute',\n left: -5,\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={handleBaseId}>\n <Handle\n id={`${handleBaseId}-target`}\n type=\"target\"\n position={Position.Left}\n isConnectable={true}\n style={handleStyle}\n />\n <Handle\n id={`${handleBaseId}-source`}\n type=\"source\"\n position={Position.Left}\n isConnectable={true}\n style={handleStyle}\n />\n </React.Fragment>\n );\n }\n \n return handles;\n };\n \n // Render output handles on the right\n const renderOutputHandles = () => {\n const handles: React.ReactElement[] = [];\n const startTop = padding + (height - outputHandlesHeight) / 2;\n \n for (let i = 0; i < outputCountNum; i++) {\n const handleBaseId = `output-${i + 1}`;\n const top = startTop + (i * (handleSize + handleSpacing));\n const portColor = getHandleColor(handleBaseId);\n \n const handleStyle: React.CSSProperties = {\n position: 'absolute',\n right: -5,\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={handleBaseId}>\n <Handle\n id={`${handleBaseId}-target`}\n type=\"target\"\n position={Position.Right}\n isConnectable={true}\n style={handleStyle}\n />\n <Handle\n id={`${handleBaseId}-source`}\n type=\"source\"\n position={Position.Right}\n isConnectable={true}\n style={handleStyle}\n />\n </React.Fragment>\n );\n }\n \n return handles;\n };\n \n // Trapezoid shape (narrower on left, wider on right)\n // Left edge height based on input handles - increased for taller flat edge\n const leftEdgeHeight = Math.max(inputHandlesHeight + (padding * 4), minHeight * 0.6); // Minimum 60% of minHeight, with extra padding\n const leftTop = (height - leftEdgeHeight) / 2;\n const leftBottom = leftTop + leftEdgeHeight;\n const rightTop = 0;\n const rightBottom = height;\n \n const borderColor = selected ? '#3b82f6' : '#4b5563';\n \n return (\n <div\n className={`trapezoid-node ${selected ? 'selected' : ''}`}\n style={{\n width,\n height,\n position: 'relative',\n background: 'transparent',\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 {/* Trapezoid border (no fill) */}\n <svg\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: `${width}px`,\n height: `${height}px`,\n pointerEvents: 'none',\n zIndex: 0,\n }}\n >\n <polygon\n points={`0,${leftTop} 0,${leftBottom} ${width},${rightBottom} ${width},${rightTop}`}\n fill=\"#1f2937\"\n stroke={borderColor}\n strokeWidth=\"2\"\n />\n </svg>\n \n {/* Left side handles */}\n {renderInputHandles()}\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 {renderOutputHandles()}\n </div>\n );\n};\n","import type { NetworkNode } from '../types';\n\nexport const isFiberNode = (node?: NetworkNode) =>\n node?.type === 'tube' ||\n node?.type === 'splice' ||\n node?.type === 'coupler' ||\n node?.type === 'fibre-split' ||\n node?.type === 'cable' ||\n node?.type === 'multi-tube-cable';\n\nexport const isFiberConnection = (sourceNode?: NetworkNode, targetNode?: NetworkNode) =>\n isFiberNode(sourceNode) || isFiberNode(targetNode);\n\nexport const normalizeHandle = (node?: NetworkNode, handle?: string | null) => {\n if (!handle) return handle || '';\n if (node?.type === 'fibre-split') {\n return handle.replace(/-(source|target)$/i, '');\n }\n return handle;\n};\n","import type { NetworkEdge, NetworkNode } from '../types';\nimport { isFiberConnection, normalizeHandle } from '../utils/connection-rules';\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 // Find source and target nodes to check their types\n const sourceNode = ctx.nodes.find(n => n.id === params.source);\n const targetNode = ctx.nodes.find(n => n.id === params.target);\n\n // UNIVERSAL RULE: Prevent multiple connections to ANY handle\n const normalizedSourceHandle = normalizeHandle(sourceNode, params.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode, params.targetHandle);\n\n // Check if source handle is already connected (in either direction)\n const sourceHandleAlreadyConnected = ctx.edges.some((e) => {\n if (e.source === params.source) {\n return normalizeHandle(sourceNode, e.sourceHandle) === normalizedSourceHandle;\n }\n if (e.target === params.source) {\n return normalizeHandle(sourceNode, e.targetHandle) === normalizedSourceHandle;\n }\n return false;\n });\n \n // Check if target handle is already connected (in either direction)\n const targetHandleAlreadyConnected = ctx.edges.some((e) => {\n if (e.target === params.target) {\n return normalizeHandle(targetNode, e.targetHandle) === normalizedTargetHandle;\n }\n if (e.source === params.target) {\n return normalizeHandle(targetNode, e.sourceHandle) === normalizedTargetHandle;\n }\n return false;\n });\n\n const fiberConnection = isFiberConnection(sourceNode, targetNode);\n\n if (sourceHandleAlreadyConnected || targetHandleAlreadyConnected) {\n if (!fiberConnection) {\n if (sourceHandleAlreadyConnected) {\n return { valid: false, reason: `Source handle ${params.sourceHandle} on node ${params.source} is already connected` };\n }\n return { valid: false, reason: `Target handle ${params.targetHandle} on node ${params.target} is already connected` };\n }\n }\n\n const isTubeFiberHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'tube' || node?.type === 'cable') && !!handle && handle.startsWith('fiber-');\n const isTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'tube' || node?.type === 'multi-tube-cable') && !!handle && handle.startsWith('tube-');\n const isCableTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'multi-tube-cable' && !!handle && handle.startsWith('tube-');\n const isTubeTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'tube' && !!handle && handle.startsWith('tube-');\n const isCableHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'cable' || node?.type === 'multi-tube-cable') && handle === 'cable-button';\n const isSpliceHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'splice' && (handle === 'left' || handle === 'right');\n const isCouplerHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'coupler' && !!handle && (handle.startsWith('left-') || handle.startsWith('right-'));\n const isSplitterHandle = (node?: NetworkNode, handle?: string | null) => {\n if (node?.type !== 'fibre-split' || !handle) return false;\n const normalized = normalizeHandle(node, handle);\n return normalized.startsWith('input-') || normalized.startsWith('output-');\n };\n\n if (!fiberConnection) {\n return { valid: true };\n }\n\n if (sourceNode?.type === 'splice' && targetNode?.type === 'splice') {\n const sourceIsRibbon = sourceNode.data?.mode === 'ribbon';\n const targetIsRibbon = targetNode.data?.mode === 'ribbon';\n if (sourceIsRibbon !== targetIsRibbon) {\n return { valid: false, reason: 'Ribbon splices can only connect to other ribbon splices' };\n }\n }\n\n const sourceIsTubeFiber = isTubeFiberHandle(sourceNode, params.sourceHandle);\n const targetIsTubeFiber = isTubeFiberHandle(targetNode, params.targetHandle);\n const sourceIsSplice = isSpliceHandle(sourceNode, params.sourceHandle);\n const targetIsSplice = isSpliceHandle(targetNode, params.targetHandle);\n const sourceIsCoupler = isCouplerHandle(sourceNode, params.sourceHandle);\n const targetIsCoupler = isCouplerHandle(targetNode, params.targetHandle);\n const sourceIsSplitter = isSplitterHandle(sourceNode, params.sourceHandle);\n const targetIsSplitter = isSplitterHandle(targetNode, params.targetHandle);\n const sourceIsCable = isCableHandle(sourceNode, params.sourceHandle);\n const targetIsCable = isCableHandle(targetNode, params.targetHandle);\n const sourceIsCableTube = isCableTubeHandle(sourceNode, params.sourceHandle);\n const targetIsCableTube = isCableTubeHandle(targetNode, params.targetHandle);\n const sourceIsTubeTube = isTubeTubeHandle(sourceNode, params.sourceHandle);\n const targetIsTubeTube = isTubeTubeHandle(targetNode, params.targetHandle);\n const sourceIsTubeHandle = isTubeHandle(sourceNode, params.sourceHandle);\n const targetIsTubeHandle = isTubeHandle(targetNode, params.targetHandle);\n\n const tubeFiberToSplice = (sourceIsTubeFiber && targetIsSplice) || (targetIsTubeFiber && sourceIsSplice);\n const spliceToCouplerOrSplitter =\n (sourceIsSplice && (targetIsCoupler || targetIsSplitter)) ||\n (targetIsSplice && (sourceIsCoupler || sourceIsSplitter));\n const couplerToCouplerSplitterOrSplice =\n (sourceIsCoupler && (targetIsCoupler || targetIsSplitter || targetIsSplice)) ||\n (targetIsCoupler && (sourceIsCoupler || sourceIsSplitter || sourceIsSplice));\n const cableToCable = sourceIsCable && targetIsCable;\n const cableToTube = (sourceIsCableTube && targetIsTubeTube) || (targetIsCableTube && sourceIsTubeTube);\n\n if (tubeFiberToSplice || spliceToCouplerOrSplitter || couplerToCouplerSplitterOrSplice || cableToCable || cableToTube) {\n return { valid: true };\n }\n\n if (sourceIsTubeHandle && targetIsTubeHandle) {\n return { valid: false, reason: 'Tube handles can only connect between cable and tube nodes' };\n }\n\n return { valid: false, reason: 'Connection not allowed by fiber rules' };\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 // Use custom width if provided, otherwise default to RACK_WIDTH_PX (300px for standard 48.26cm/19\" rack)\n const rackWidth = rack.data.rackWidthPx || 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 { MultiTubeCableNode } from './MultiTubeCableNode';\nimport { CouplerNode } from './CouplerNode';\nimport { PatchPanelNode } from './PatchPanelNode';\nimport { ClosureNode } from './ClosureNode';\nimport { FibreSplitNode } from './FibreSplitNode';\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, calculateSplicePositionFromNumberWithData } from '../utils/splice-positioning';\nimport { isFiberConnection, normalizeHandle } from '../utils/connection-rules';\n\n// ============================================================================\n// RIBBON MODE vs NORMAL MODE HELPERS\n// ============================================================================\n// These helper functions clearly separate the logic for ribbon mode vs normal mode\n\n/**\n * Determines if a splice node is in ribbon mode\n */\nfunction isSpliceRibbonMode(spliceNode: NetworkNode | undefined): boolean {\n if (!spliceNode || spliceNode.type !== 'splice') return false;\n const spliceData = spliceNode.data as NetworkNode['data'];\n return spliceData?.mode === 'ribbon';\n}\n\n// ============================================================================\n// END RIBBON MODE vs NORMAL MODE HELPERS\n// ============================================================================\n\n// Wrapper component that adds data-type attribute to React Flow node wrapper\n// React Flow doesn't natively set data-type, so we add it for testing/querying purposes\n// Uses ref callback + useEffect to ensure attribute is set reliably\nconst NodeWithDataType: React.FC<{ type: string; children: React.ReactNode }> = ({ type, children }) => {\n const wrapperRef = React.useRef<HTMLDivElement>(null);\n \n // Set data-type on React Flow's node wrapper using ref callback (synchronous)\n const setDataTypeRef = React.useCallback((element: HTMLDivElement | null) => {\n wrapperRef.current = element;\n if (element) {\n // Find the React Flow wrapper (parent with class react-flow__node)\n let parent = element.parentElement;\n let attempts = 0;\n while (parent && !parent.classList.contains('react-flow__node') && attempts < 10) {\n parent = parent.parentElement;\n attempts++;\n }\n if (parent && parent.classList.contains('react-flow__node')) {\n parent.setAttribute('data-type', type);\n }\n }\n }, [type]);\n \n // Fallback: also set in useEffect in case ref callback runs before parent is mounted\n React.useEffect(() => {\n if (wrapperRef.current) {\n let parent = wrapperRef.current.parentElement;\n let attempts = 0;\n while (parent && !parent.classList.contains('react-flow__node') && attempts < 10) {\n parent = parent.parentElement;\n attempts++;\n }\n if (parent && parent.classList.contains('react-flow__node')) {\n parent.setAttribute('data-type', type);\n }\n }\n }, [type]);\n \n return (\n <div \n ref={setDataTypeRef} \n style={{ width: '100%', height: '100%' }}\n >\n {children}\n </div>\n );\n};\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']>) => (\n <NodeWithDataType type=\"rack\">\n <RackNode {...props} onViewChange={onViewChange} onRackFaceChange={onRackFaceChange} isDragOver={getDragOverRackId ? getDragOverRackId() === props.id : false} />\n </NodeWithDataType>\n ),\n fiber: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"fiber\">\n <FiberNode {...props} />\n </NodeWithDataType>\n ),\n device: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"device\">\n <DeviceNode {...props} />\n </NodeWithDataType>\n ),\n 'vertical-pdu': (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"vertical-pdu\">\n <VerticalPDU {...props} />\n </NodeWithDataType>\n ),\n splice: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"splice\">\n <SpliceNode {...props} />\n </NodeWithDataType>\n ),\n 'splice-tray': (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"splice-tray\">\n <SpliceTrayNode {...props} />\n </NodeWithDataType>\n ),\n tube: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"tube\">\n <TubeNode {...props} />\n </NodeWithDataType>\n ),\n cable: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"cable\">\n <CableNode {...props} />\n </NodeWithDataType>\n ),\n 'multi-tube-cable': (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"multi-tube-cable\">\n <MultiTubeCableNode {...props} />\n </NodeWithDataType>\n ),\n coupler: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"coupler\">\n <CouplerNode {...props} />\n </NodeWithDataType>\n ),\n 'patch-panel': (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"patch-panel\">\n <PatchPanelNode {...props} />\n </NodeWithDataType>\n ),\n closure: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"closure\">\n <ClosureNode {...props} />\n </NodeWithDataType>\n ),\n 'fibre-split': (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"fibre-split\">\n <FibreSplitNode {...props} />\n </NodeWithDataType>\n ),\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 useSmoothstepEdgesForTubes = false,\n connectOnClick = true,\n panOnDrag = true,\n panOnScroll = true,\n zoomOnScroll = true,\n}) => {\n // Function to validate and filter edges to remove duplicate handle connections\n const validateAndFilterEdges = useCallback((edgesToValidate: NetworkEdge[], nodesForValidation: NetworkNode[]): NetworkEdge[] => {\n const seenHandles = new Map<string, NetworkEdge>(); // Map of \"nodeId:handleId\" -> first edge using it\n const validEdges: NetworkEdge[] = [];\n const removedEdges: NetworkEdge[] = [];\n\n // Special handles that allow replacement (but we still track them)\n const isSpecialHandle = (handle: string, node?: NetworkNode) => {\n if (!handle || !node) return false;\n if (handle.startsWith('tube-')) return true;\n if (node.type === 'splice' && (handle === 'left' || handle === 'right')) return true;\n if (handle === 'cable-button') return true;\n return false;\n };\n\n for (const edge of edgesToValidate) {\n if (!edge.source || !edge.target || !edge.sourceHandle || !edge.targetHandle) {\n // Invalid edge, skip it\n if (debug) {\n console.warn('Invalid edge skipped (missing source/target/handles):', edge);\n }\n continue;\n }\n\n const sourceNode = nodesForValidation.find(n => n.id === edge.source);\n const targetNode = nodesForValidation.find(n => n.id === edge.target);\n\n // Check source handle\n const sourceHandleKey = `${edge.source}:${edge.sourceHandle}`;\n const existingSourceEdge = seenHandles.get(sourceHandleKey);\n const isSourceSpecial = isSpecialHandle(edge.sourceHandle, sourceNode);\n\n // Check target handle\n const targetHandleKey = `${edge.target}:${edge.targetHandle}`;\n const existingTargetEdge = seenHandles.get(targetHandleKey);\n const isTargetSpecial = isSpecialHandle(edge.targetHandle, targetNode);\n\n // For non-special handles, reject if already used\n if (existingSourceEdge && !isSourceSpecial) {\n if (debug) {\n console.warn('Duplicate connection detected on source handle, removing:', {\n handle: sourceHandleKey,\n existingEdge: existingSourceEdge.id,\n duplicateEdge: edge.id,\n });\n }\n removedEdges.push(edge);\n continue;\n }\n\n if (existingTargetEdge && !isTargetSpecial) {\n if (debug) {\n console.warn('Duplicate connection detected on target handle, removing:', {\n handle: targetHandleKey,\n existingEdge: existingTargetEdge.id,\n duplicateEdge: edge.id,\n });\n }\n removedEdges.push(edge);\n continue;\n }\n\n // Edge is valid, add it and track its handles\n validEdges.push(edge);\n if (!existingSourceEdge) {\n seenHandles.set(sourceHandleKey, edge);\n }\n if (!existingTargetEdge) {\n seenHandles.set(targetHandleKey, edge);\n }\n }\n\n if (debug && removedEdges.length > 0) {\n console.log(`Filtered ${removedEdges.length} duplicate edge(s) from initial edges`);\n }\n\n return validEdges;\n }, [debug]);\n\n // Decide controlled vs uncontrolled\n const isControlled = Array.isArray(nodes) && Array.isArray(edges);\n \n // Validate and filter initial edges to remove duplicates\n const initialNodesForValidation = React.useMemo(() => {\n return isControlled ? (nodes || []) : (initialNodes || nodes || []);\n }, [isControlled, nodes, initialNodes]);\n \n const initialEdgesRaw = React.useMemo(() => {\n return isControlled ? (edges || []) : (initialEdges || edges || []);\n }, [isControlled, edges, initialEdges]);\n \n const validatedInitialEdges = React.useMemo(() => {\n return validateAndFilterEdges(initialEdgesRaw, initialNodesForValidation);\n }, [initialEdgesRaw, initialNodesForValidation, validateAndFilterEdges]);\n\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: initialNodesForValidation,\n edges: validatedInitialEdges,\n debug,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [store, isControlled, debug, validatedInitialEdges]);\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 // Detect mobile device for hiding MiniMap\n const [isMobile, setIsMobile] = useState<boolean>(false);\n useEffect(() => {\n const checkMobile = () => {\n setIsMobile(window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));\n };\n checkMobile();\n window.addEventListener('resize', checkMobile);\n return () => window.removeEventListener('resize', checkMobile);\n }, []);\n \n // Get React Flow methods for save/restore\n const { toObject, setViewport, setNodes: setReactFlowNodes, setEdges: setReactFlowEdges, getNodes, getEdges, fitView } = 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 getNodes: () => getNodes(),\n getEdges: () => getEdges(),\n fitView: (options?: { nodes?: string[]; padding?: number; maxZoom?: number; minZoom?: number; duration?: number }) => {\n // Convert string IDs to Node objects if nodes are provided as strings\n if (options?.nodes && Array.isArray(options.nodes) && options.nodes.length > 0) {\n const nodeObjects = options.nodes\n .map(id => getNodes().find(n => n.id === id))\n .filter((n): n is Node => n !== undefined);\n // Create new options object without nodes, then add converted nodes\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { nodes: _unused, ...restOptions } = options;\n fitView({ ...restOptions, nodes: nodeObjects });\n } else {\n // If no nodes provided or empty, pass options as-is (without nodes property)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { nodes: _unused, ...restOptions } = options || {};\n fitView(restOptions);\n }\n }\n });\n }\n }, [onFlowMethods, toObject, setViewport, setReactFlowNodes, setReactFlowEdges, localStore, fitView, getNodes, getEdges]);\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 wrapper functions using useCallback with empty deps\n // These functions access refs via .current, so they can be stable even when callbacks change\n const onViewChangeStable = useCallback((nodeId: string, view: 'front' | 'rear') => {\n onViewChangeRef.current?.(nodeId, view);\n }, []);\n \n const onRackFaceChangeStable = useCallback((rackId: string, face: 'front' | 'rear') => {\n onRackFaceChangeRef.current?.(rackId, face);\n }, []);\n \n const getDragOverRackIdStable = useCallback(() => dragOverRackIdRef.current, []);\n \n // Store nodeTypes in a ref to ensure stable reference across renders\n // This prevents React Flow from detecting it as a new object\n const nodeTypesRef = useRef<NodeTypes>(\n createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n )\n );\n \n // Update nodeTypes ref only when stable callbacks change (they shouldn't, but just in case)\n useEffect(() => {\n nodeTypesRef.current = createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n );\n }, [onViewChangeStable, onRackFaceChangeStable, getDragOverRackIdStable]);\n \n // edgeTypes is already defined outside component as a constant, so use it directly\n // No memoization needed since it's already stable\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 // Also validate edges when they're updated in controlled mode\n useEffect(() => {\n if (isControlled && edges) {\n const validated = validateAndFilterEdges(edges, nodes || []);\n if (validated.length !== edges.length) {\n if (debug) {\n console.warn(`Controlled edges had ${edges.length - validated.length} duplicate(s) removed`);\n }\n // Update edges to remove duplicates\n externalOnEdgesChange?.(validated);\n }\n }\n }, [isControlled, edges, nodes, validateAndFilterEdges, externalOnEdgesChange, debug]);\n \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 // Cache node lookup map for O(1) lookups instead of O(n) array search\n const nodesMapRef = useRef<Map<string, Node>>(new Map());\n useEffect(() => {\n // Update map when nodes change\n const map = new Map<string, Node>();\n reactFlowNodes.forEach(node => {\n map.set(node.id, node);\n });\n nodesMapRef.current = map;\n }, [reactFlowNodes]);\n \n const getNodeById = useCallback((id: string) => {\n return nodesMapRef.current.get(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 multi-tube 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 const normalizedHandle = sourceHandle.replace(/-(source|target)$/i, '');\n \n // For WDM/splitter output handles, inherit color from the input edge that feeds this output\n // Check if there's an incoming edge to the input handles, then propagate to outputs\n if (sourceNode.type === 'fibre-split' && normalizedHandle.startsWith('output-')) {\n // For WDM outputs, check if there's an incoming edge to any input handle\n // The output color should match the input color (or first input if multiple)\n const inputEdges = latestEdgesRef.current.filter(\n (e) => e.target === sourceNodeId && (e.targetHandle || '').replace(/-(source|target)$/i, '').startsWith('input-')\n ) as NetworkEdge[];\n if (inputEdges.length > 0) {\n // Use the first input edge's color\n const inputColor = inputEdges[0]?.data?.color;\n if (inputColor) {\n return { color: inputColor };\n }\n }\n }\n \n // For tube or cable nodes, extract fiber number from handle ID (format: \"fiber-<n>\")\n if ((sourceNode.type === 'tube' || sourceNode.type === 'cable') && 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 === 'multi-tube-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 - only update if zIndex actually changed\n const edgesZIndexRef = useRef<Map<string, number>>(new Map());\n useEffect(() => {\n setEdges((eds) => {\n let hasChanges = false;\n const updated = eds.map(edge => {\n const newZIndex = selectEdgeZIndex(edge as NetworkEdge);\n const oldZIndex = edgesZIndexRef.current.get(edge.id);\n if (oldZIndex !== newZIndex) {\n hasChanges = true;\n edgesZIndexRef.current.set(edge.id, newZIndex);\n return {\n ...edge,\n zIndex: newZIndex,\n style: { ...edge.style, zIndex: newZIndex }\n };\n }\n return edge;\n });\n return hasChanges ? updated : eds;\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 isRibbonMode = node.data.mode === 'ribbon';\n const calculatedPosition = calculateSplicePositionFromNumberWithData(parentTray as NetworkNode, node.data.holderPosition, isRibbonMode);\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 // Prevent tubes and trays from being moved inside closures (they're locked in position)\n if (node && (node.type === 'tube' || node.type === 'splice-tray') && node.parentId) {\n const parentClosure = getNodeById(node.parentId);\n if (parentClosure && parentClosure.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 const normalizedSourceHandle = normalizeHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n\n // UNIVERSAL RULE: Prevent multiple connections to ANY handle\n const sourceHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.source === connection.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle;\n }\n if (e.target === connection.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle;\n }\n return false;\n });\n const targetHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.target === connection.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle;\n }\n if (e.source === connection.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle;\n }\n return false;\n });\n\n if (sourceHandleAlreadyConnected && debug) {\n console.log('Connection will replace: Source handle already connected', {\n source: connection.source,\n sourceHandle: connection.sourceHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.source === connection.source && e.sourceHandle === connection.sourceHandle) ||\n (e.target === connection.source && e.targetHandle === connection.sourceHandle)\n )\n });\n }\n\n if (targetHandleAlreadyConnected && debug) {\n console.log('Connection will replace: Target handle already connected', {\n target: connection.target,\n targetHandle: connection.targetHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.target === connection.target && e.targetHandle === connection.targetHandle) ||\n (e.source === connection.target && e.sourceHandle === connection.targetHandle)\n )\n });\n }\n\n const fiberConnection = isFiberConnection(sourceNode as NetworkNode | undefined, targetNode as NetworkNode | undefined);\n\n if ((sourceHandleAlreadyConnected || targetHandleAlreadyConnected) && !fiberConnection) {\n if (debug) {\n console.log('Connection rejected: Non-fiber handle already connected', connection);\n }\n return false;\n }\n\n if (!fiberConnection) {\n return true;\n }\n\n if (sourceNode?.type === 'splice' && targetNode?.type === 'splice') {\n const sourceIsRibbon = sourceNode.data?.mode === 'ribbon';\n const targetIsRibbon = targetNode.data?.mode === 'ribbon';\n if (sourceIsRibbon !== targetIsRibbon) {\n if (debug) {\n console.log('Connection rejected: Ribbon splices can only connect to other ribbon splices', connection);\n }\n return false;\n }\n }\n\n const isTubeFiberHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'tube' || node?.type === 'cable') && !!handle && handle.startsWith('fiber-');\n const isTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'tube' || node?.type === 'multi-tube-cable') && !!handle && handle.startsWith('tube-');\n const isCableTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'multi-tube-cable' && !!handle && handle.startsWith('tube-');\n const isTubeTubeHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'tube' && !!handle && handle.startsWith('tube-');\n const isCableHandle = (node?: NetworkNode, handle?: string | null) =>\n (node?.type === 'cable' || node?.type === 'multi-tube-cable') && handle === 'cable-button';\n const isSpliceHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'splice' && (handle === 'left' || handle === 'right');\n const isCouplerHandle = (node?: NetworkNode, handle?: string | null) =>\n node?.type === 'coupler' && !!handle && (handle.startsWith('left-') || handle.startsWith('right-'));\n const isSplitterHandle = (node?: NetworkNode, handle?: string | null) => {\n if (node?.type !== 'fibre-split' || !handle) return false;\n const normalized = handle.replace(/-(source|target)$/i, '');\n return normalized.startsWith('input-') || normalized.startsWith('output-');\n };\n\n const sourceIsTubeFiber = isTubeFiberHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsTubeFiber = isTubeFiberHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsSplice = isSpliceHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsSplice = isSpliceHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsCoupler = isCouplerHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsCoupler = isCouplerHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsSplitter = isSplitterHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsSplitter = isSplitterHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsCable = isCableHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsCable = isCableHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsCableTube = isCableTubeHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsCableTube = isCableTubeHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsTubeTube = isTubeTubeHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsTubeTube = isTubeTubeHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n const sourceIsTubeHandle = isTubeHandle(sourceNode as NetworkNode | undefined, connection.sourceHandle);\n const targetIsTubeHandle = isTubeHandle(targetNode as NetworkNode | undefined, connection.targetHandle);\n\n const tubeFiberToSplice = (sourceIsTubeFiber && targetIsSplice) || (targetIsTubeFiber && sourceIsSplice);\n const spliceToCouplerOrSplitter =\n (sourceIsSplice && (targetIsCoupler || targetIsSplitter)) ||\n (targetIsSplice && (sourceIsCoupler || sourceIsSplitter));\n const couplerToCouplerSplitterOrSplice =\n (sourceIsCoupler && (targetIsCoupler || targetIsSplitter || targetIsSplice)) ||\n (targetIsCoupler && (sourceIsCoupler || sourceIsSplitter || sourceIsSplice));\n const cableToCable = sourceIsCable && targetIsCable;\n const cableToTube = (sourceIsCableTube && targetIsTubeTube) || (targetIsCableTube && sourceIsTubeTube);\n\n if (tubeFiberToSplice || spliceToCouplerOrSplitter || couplerToCouplerSplitterOrSplice || cableToCable || cableToTube) {\n return true;\n }\n\n if (sourceIsTubeHandle && targetIsTubeHandle) {\n if (debug) {\n console.log('Connection rejected: Tube handles can only connect between cable and tube nodes', connection);\n }\n return false;\n }\n\n if (debug) {\n console.log('Connection rejected: Connection not allowed by fiber rules', connection);\n }\n return false;\n }, [getNodeById, debug]);\n\n const onConnect = useCallback(\n (params: Connection) => {\n if (debug) {\n console.log('onConnect called:', params);\n }\n const sourceNode = getNodeById(params.source!);\n const targetNode = getNodeById(params.target!);\n \n if (debug) {\n console.log('onConnect: sourceNode type:', sourceNode?.type, 'targetNode type:', targetNode?.type);\n console.log('onConnect: sourceHandle:', params.sourceHandle, 'targetHandle:', params.targetHandle);\n }\n\n const initialValidation = 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 (!initialValidation.valid) {\n if (debug) {\n console.warn(`Connection rejected: ${initialValidation.reason}`);\n }\n return;\n }\n\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 === 'multi-tube-cable';\n const isCableToTube = sourceNode?.type === 'multi-tube-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 // For tube-to-cable connections: derive color from TARGET (multi-tube cable tube) so tube node border matches tube color\n // For cable-to-tube connections: derive color from SOURCE (multi-tube cable tube) so edge matches tube color\n let edgeData: { color?: string; striped?: boolean; ribbonFiberIds?: number[]; isRibbon?: boolean } | undefined;\n \n // RIBBON MODE: Check if connecting to/from a ribbon splice - if so, add ribbon data for multi-color ribbon edge\n const isRibbonSpliceTarget = isSpliceRibbonMode(targetNode as NetworkNode);\n const isRibbonSpliceSource = isSpliceRibbonMode(sourceNode as NetworkNode);\n \n if (isRibbonSpliceTarget || isRibbonSpliceSource) {\n const targetSpliceData = targetNode?.data as NetworkNode['data'];\n const sourceSpliceData = sourceNode?.data as NetworkNode['data'];\n // Get ribbon fiber IDs from splice node data if available\n const ribbonFiberIds = isRibbonSpliceTarget \n ? targetSpliceData.ribbonFiberIds \n : sourceSpliceData.ribbonFiberIds;\n \n if (ribbonFiberIds && Array.isArray(ribbonFiberIds) && ribbonFiberIds.length >= 6 && ribbonFiberIds.length <= 12) {\n // Add ribbon data so edge renders as multi-color ribbon (not grey)\n edgeData = {\n ribbonFiberIds,\n isRibbon: true,\n // Don't set color - let ribbon edge render with its multi-color gradient\n };\n }\n }\n \n // If not a ribbon splice, derive normal fiber color\n if (!edgeData && (edgeType === 'fiber' || edgeType === 'smoothstep') && !isPduSource) {\n let colorInfo;\n if (isTubeToCable) {\n // Tube-to-cable: derive from target (multi-tube cable tube handle) so tube node border matches tube color\n colorInfo = deriveFiberColorFromSource(params.target!, params.targetHandle);\n } else {\n // Cable-to-tube or other: derive from source handle\n colorInfo = deriveFiberColorFromSource(params.source!, params.sourceHandle);\n }\n if (colorInfo) {\n edgeData = { color: colorInfo.color, striped: colorInfo.striped, isRibbon: false };\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 const normalizedSourceHandle = normalizeHandle(sourceNode as NetworkNode | undefined, params.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, params.targetHandle);\n const sourceHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.source === params.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle;\n }\n if (e.target === params.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle;\n }\n return false;\n });\n const targetHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.target === params.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle;\n }\n if (e.source === params.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle;\n }\n return false;\n });\n const fiberConnection = isFiberConnection(sourceNode as NetworkNode | undefined, targetNode as NetworkNode | undefined);\n\n if (fiberConnection && (sourceHandleAlreadyConnected || targetHandleAlreadyConnected)) {\n const edgesToRemove = new Set<string>();\n for (const edge of latestEdgesRef.current) {\n if (edge.source === params.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.sourceHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === params.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.targetHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.source === params.target) {\n if (normalizeHandle(targetNode as NetworkNode | undefined, edge.sourceHandle) === normalizedTargetHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === params.target) {\n if (normalizeHandle(targetNode as NetworkNode | undefined, edge.targetHandle) === normalizedTargetHandle) {\n edgesToRemove.add(edge.id);\n }\n }\n }\n\n if (edgesToRemove.size > 0) {\n const filtered = latestEdgesRef.current.filter(e => !edgesToRemove.has(e.id));\n const edgeFromAddEdge = addEdge(params, filtered);\n const newEdge = edgeFromAddEdge[edgeFromAddEdge.length - 1];\n const zIndex = selectEdgeZIndex({ ...params, 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: edgeData !== undefined ? edgeData : newEdge.data,\n };\n\n setEdges([...edgeFromAddEdge.slice(0, -1), edgeWithMetadata]);\n if (debug) {\n console.log('Fiber handle replacement: Replaced', edgesToRemove.size, 'edge(s)');\n }\n return;\n }\n }\n\n // SPLICE HANDLE REPLACEMENT: Check splice handles FIRST before general replacement\n // This ensures splice handle replacement works correctly when connecting from tube fibers\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 directions\n // This works for BOTH normal mode and ribbon mode\n if (targetNode?.type === 'splice' && (params.targetHandle === 'left' || params.targetHandle === 'right') && params.target && params.targetHandle) {\n // Find existing edge connected to this splice handle (check both directions)\n const existingSpliceEdge = latestEdgesRef.current.find(\n (e) => (e.target === params.target && e.targetHandle === params.targetHandle) ||\n (e.source === params.target && e.sourceHandle === params.targetHandle)\n );\n if (existingSpliceEdge) {\n if (debug) {\n console.log('Splice target handle replacement: Found existing edge', existingSpliceEdge.id, 'on splice handle', params.targetHandle);\n console.log('Existing edge details:', {\n id: existingSpliceEdge.id,\n source: existingSpliceEdge.source,\n target: existingSpliceEdge.target,\n sourceHandle: existingSpliceEdge.sourceHandle,\n targetHandle: existingSpliceEdge.targetHandle,\n data: existingSpliceEdge.data\n });\n }\n // Also check if source handle (e.g., tube fiber) is already connected to something else\n // and remove that edge too to avoid duplicate connections\n const existingSourceEdge = params.source && params.sourceHandle\n ? latestEdgesRef.current.find(\n (e) => e.source === params.source && e.sourceHandle === params.sourceHandle\n )\n : null;\n \n if (debug && existingSourceEdge) {\n console.log('Splice target handle replacement: Also found existing source edge', existingSourceEdge.id);\n }\n \n // Remove both edges if they exist (they might be the same edge)\n const edgesToRemove = new Set<string>();\n if (existingSpliceEdge) edgesToRemove.add(existingSpliceEdge.id);\n if (existingSourceEdge && existingSourceEdge.id !== existingSpliceEdge.id) {\n edgesToRemove.add(existingSourceEdge.id);\n }\n \n const filtered = latestEdgesRef.current.filter(e => !edgesToRemove.has(e.id));\n \n if (debug) {\n console.log('Splice target handle replacement: Removing', edgesToRemove.size, 'edge(s), creating new connection');\n }\n \n // Manually create the new edge instead of using addEdge to ensure it's created\n // This works more reliably than addEdge which might have internal validation\n const newEdgeId = `edge-${params.source}-${params.sourceHandle}-${params.target}-${params.targetHandle}-${Date.now()}`;\n const zIndex = selectEdgeZIndex({ ...params, id: newEdgeId, type: 'fiber' } as NetworkEdge);\n const newEdge: Edge = {\n id: newEdgeId,\n source: params.source!,\n target: params.target!,\n sourceHandle: params.sourceHandle!,\n targetHandle: params.targetHandle!,\n type: 'fiber',\n zIndex: zIndex,\n style: { zIndex: zIndex },\n data: edgeData !== undefined ? edgeData : {},\n };\n \n const newEdges = [...filtered, newEdge];\n setEdges(newEdges);\n if (debug) {\n console.log('Splice target handle replacement: Successfully replaced edge with new edge', newEdge.id);\n }\n return;\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 directions\n if (sourceNode?.type === 'splice' && params.sourceHandle === 'right' && params.source && params.sourceHandle) {\n // Find existing edge connected to this splice handle (check both directions)\n const existingSpliceEdge = latestEdgesRef.current.find(\n (e) => (e.source === params.source && e.sourceHandle === params.sourceHandle) ||\n (e.target === params.source && e.targetHandle === params.sourceHandle)\n );\n if (existingSpliceEdge) {\n if (debug) {\n console.log('Splice source handle replacement: Found existing edge', existingSpliceEdge.id, 'on splice handle', params.sourceHandle);\n }\n // Also check if target handle (e.g., tube fiber) is already connected to something else\n // and remove that edge too to avoid duplicate connections\n const existingTargetEdge = params.target && params.targetHandle\n ? latestEdgesRef.current.find(\n (e) => e.target === params.target && e.targetHandle === params.targetHandle\n )\n : null;\n \n if (debug && existingTargetEdge) {\n console.log('Splice source handle replacement: Also found existing target edge', existingTargetEdge.id);\n }\n \n // Remove both edges if they exist (they might be the same edge)\n const edgesToRemove = new Set<string>();\n if (existingSpliceEdge) edgesToRemove.add(existingSpliceEdge.id);\n if (existingTargetEdge && existingTargetEdge.id !== existingSpliceEdge.id) {\n edgesToRemove.add(existingTargetEdge.id);\n }\n \n const filtered = latestEdgesRef.current.filter(e => !edgesToRemove.has(e.id));\n \n if (debug) {\n console.log('Splice source handle replacement: Removing', edgesToRemove.size, 'edge(s), creating new connection');\n }\n \n // Manually create the new edge instead of using addEdge to ensure it's created\n // This works more reliably than addEdge which might have internal validation\n const newEdgeId = `edge-${params.source}-${params.sourceHandle}-${params.target}-${params.targetHandle}-${Date.now()}`;\n const zIndex = selectEdgeZIndex({ ...params, id: newEdgeId, type: 'fiber' } as NetworkEdge);\n const newEdge: Edge = {\n id: newEdgeId,\n source: params.source!,\n target: params.target!,\n sourceHandle: params.sourceHandle!,\n targetHandle: params.targetHandle!,\n type: 'fiber',\n zIndex: zIndex,\n style: { zIndex: zIndex },\n data: edgeData !== undefined ? edgeData : {},\n };\n \n const newEdges = [...filtered, newEdge];\n setEdges(newEdges);\n if (debug) {\n console.log('Splice source handle replacement: Successfully replaced edge with new edge', newEdge.id);\n }\n return;\n }\n }\n\n // Replace existing edge on tube fiber source handle - only one edge per handle\n if ((sourceNode?.type === 'tube' || sourceNode?.type === 'cable') && 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' || targetNode?.type === 'cable') && 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 === 'multi-tube-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 === 'multi-tube-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 coupler source handle - only one edge per handle\n if (sourceNode?.type === 'coupler' && (params.sourceHandle?.startsWith('left-') || params.sourceHandle?.startsWith('right-'))) {\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 coupler target handle - only one edge per handle\n if (targetNode?.type === 'coupler' && (params.targetHandle?.startsWith('left-') || params.targetHandle?.startsWith('right-'))) {\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 // 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 // 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 // FINAL SAFETY CHECK: Prevent duplicate connections even if validation passed\n // This catches any edge cases where isValidConnection might have passed due to timing\n const sourceHandleAlreadyUsed = latestEdgesRef.current.some(\n (e) => (e.source === params.source && e.sourceHandle === params.sourceHandle) ||\n (e.target === params.source && e.targetHandle === params.sourceHandle)\n );\n const targetHandleAlreadyUsed = latestEdgesRef.current.some(\n (e) => (e.target === params.target && e.targetHandle === params.targetHandle) ||\n (e.source === params.target && e.sourceHandle === params.targetHandle)\n );\n\n // Special handles that allow replacement (already handled above, but double-check)\n const isSpecialHandleForReplacement = (handle: string, node?: NetworkNode) => {\n if (!handle || !node) return false;\n if (handle.startsWith('tube-')) return true;\n if (node.type === 'splice' && (handle === 'left' || handle === 'right')) return true;\n if (handle === 'cable-button') return true;\n return false;\n };\n\n const isSourceSpecialForReplacement = isSpecialHandleForReplacement(params.sourceHandle || '', sourceNode as NetworkNode | undefined);\n const isTargetSpecialForReplacement = isSpecialHandleForReplacement(params.targetHandle || '', targetNode as NetworkNode | undefined);\n\n // If handle is already used and it's NOT a special handle, reject (should not happen, but safety check)\n if (sourceHandleAlreadyUsed && !isSourceSpecialForReplacement) {\n if (debug) {\n console.warn('FINAL SAFETY CHECK: Source handle already connected, rejecting duplicate connection', {\n source: params.source,\n sourceHandle: params.sourceHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.source === params.source && e.sourceHandle === params.sourceHandle) ||\n (e.target === params.source && e.targetHandle === params.sourceHandle)\n )\n });\n }\n return;\n }\n\n if (targetHandleAlreadyUsed && !isTargetSpecialForReplacement) {\n if (debug) {\n console.warn('FINAL SAFETY CHECK: Target handle already connected, rejecting duplicate connection', {\n target: params.target,\n targetHandle: params.targetHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.target === params.target && e.targetHandle === params.targetHandle) ||\n (e.source === params.target && e.sourceHandle === params.targetHandle)\n )\n });\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, 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 const validation = localStore.validateConnection({\n source: newConnection.source ?? null,\n target: newConnection.target ?? null,\n sourceHandle: newConnection.sourceHandle ?? null,\n targetHandle: newConnection.targetHandle ?? null,\n });\n if (!validation.valid) {\n if (debug) {\n console.warn(`Edge update rejected: ${validation.reason}`);\n }\n return;\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 === 'multi-tube-cable';\n const isCableToTube = sourceNode?.type === 'multi-tube-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 fiberConnection = isFiberConnection(sourceNode as NetworkNode | undefined, targetNode as NetworkNode | undefined);\n const normalizedSourceHandle = normalizeHandle(sourceNode as NetworkNode | undefined, newConnection.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, newConnection.targetHandle);\n\n const deduped = fiberConnection\n ? eds.filter((e) => {\n if (e.id === oldEdge.id) return true;\n const matchesSource =\n (e.source === newConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle) ||\n (e.target === newConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle);\n const matchesTarget =\n (e.target === newConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle) ||\n (e.source === newConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle);\n return !(matchesSource || matchesTarget);\n })\n : eds;\n\n const updated = deduped.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, localStore]\n );\n\n const handleNodeClick = useCallback(\n (event: React.MouseEvent, node: Node) => {\n // On mobile, don't trigger selection - just call onNodeClick without selecting\n if (isMobile) {\n if (onNodeClick) {\n onNodeClick(node as NetworkNode);\n }\n return;\n }\n\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.type === 'multi-tube-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, isMobile]\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, edges }) => {\n // Track selected edges for deletion\n setSelectedEdges(edges || []);\n \n // Don't handle selection on mobile\n if (isMobile) {\n return;\n }\n \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.type === 'multi-tube-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 // Track selected edges for deletion\n const [selectedEdges, setSelectedEdges] = useState<Edge[]>([]);\n \n // Handle keyboard events for edge deletion\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n // Delete selected edges on Backspace or Delete key\n if ((event.key === 'Backspace' || event.key === 'Delete') && selectedEdges.length > 0) {\n // Don't delete if focus is on an input element\n if (document.activeElement?.tagName === 'INPUT' || document.activeElement?.tagName === 'TEXTAREA') {\n return;\n }\n \n // Filter out tube-related edges (these cannot be deleted)\n const deletableEdges = selectedEdges.filter(edge => {\n const sourceHandle = edge.sourceHandle || '';\n const targetHandle = edge.targetHandle || '';\n const isTubeHandle = sourceHandle.startsWith('tube-') || targetHandle.startsWith('tube-');\n if (isTubeHandle) {\n if (debug) {\n console.log('Cannot delete edge connected to tube handle', edge);\n }\n return false;\n }\n return true;\n });\n \n if (deletableEdges.length > 0) {\n const edgeIdsToDelete = new Set(deletableEdges.map(e => e.id));\n setEdges((eds) => eds.filter(e => !edgeIdsToDelete.has(e.id)));\n setSelectedEdges([]);\n if (debug) {\n console.log('Deleted edges:', deletableEdges.map(e => e.id));\n }\n }\n }\n };\n \n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [selectedEdges, setEdges, debug]);\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 // Memoize with stable node map reference for better performance\n const edgesWithAnimation = useMemo(() => {\n const nodesMap = nodesMapRef.current;\n return reactFlowEdges.map(edge => {\n const e = edge as unknown as NetworkEdge;\n // Resolve endpoints using cached map (O(1) lookup)\n const sourceNode = nodesMap.get(String(e.source)) as unknown as Node | undefined;\n const targetNode = nodesMap.get(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 either endpoint is in rear view and does not use a rear handle\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]);\n\n return (\n <div \n ref={reactFlowWrapper} \n className={`${className || ''} ${colorMode === 'light' ? 'react-flow-light' : 'react-flow-dark'}`} \n style={{ \n width: '100%', \n height: '100%', \n touchAction: 'none', // Prevent default touch behaviors like scrolling\n ...style \n }}\n >\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 // But allow deletions for all other edges\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 including deletions\n });\n \n // Process all changes (including deletions for non-tube handles)\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={nodeTypesRef.current}\n edgeTypes={edgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: true\n }}\n nodesDraggable={!isMobile}\n nodesConnectable={true}\n elementsSelectable={!isMobile}\n edgesFocusable={!isMobile}\n selectNodesOnDrag={false}\n connectOnClick={connectOnClick}\n panOnDrag={panOnDrag}\n panOnScroll={panOnScroll && !isMobile}\n zoomOnScroll={zoomOnScroll && !isMobile}\n preventScrolling={isMobile}\n onlyRenderVisibleElements={true}\n fitView\n proOptions={{ hideAttribution: true }}\n >\n <Background color={colorMode === 'light' ? '#e5e5e5' : '#2a2a2a'} />\n <Controls />\n {!isMobile && <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 rackWidthPx: rack.data.rackWidthPx, // Pass through parent rack's custom width\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 rackWidthPx: rack.rackWidthPx, // Pass through optional custom width\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 rackWidthPx: rackNode.data.rackWidthPx, // Preserve custom width\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 { calculateSplicePositionFromNumberWithData, 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, using mode-aware positioning\n const isRibbonMode = splice.mode === 'ribbon';\n const position = calculateSplicePositionFromNumberWithData(tray, splice.holder, isRibbonMode);\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 mode: splice.mode || 'single',\n ribbonFiberIds: splice.ribbonFiberIds,\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 mode: spliceNode.data.mode || 'single',\n ribbonFiberIds: spliceNode.data.ribbonFiberIds,\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"]}