@mp70/react-networks 0.3.0-alpha.0 → 0.3.0-alpha.2

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/constants.ts","../src/utils/react-flow-theming.ts","../src/utils/rack-device-types.ts","../src/utils/rack-layout.ts","../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/utils/handle-ids.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/utils/endpoint-kind.ts","../src/core/store.ts","../src/core/hooks.ts","../src/utils/rack-geometry.ts","../src/utils/edge-connection.ts","../src/utils/rack-mount-mode.ts","../src/components/NetworkDiagram.tsx","../src/components/DiagramErrorBoundary.tsx","../src/utils/fibre-flow-layout.ts","../src/components/FibreFlowMap.tsx","../src/components/FibreCableWithTubesExpanded.tsx","../src/utils/inventory.ts","../src/utils/netbox.ts","../src/utils/placement-validation.ts","../src/utils/rack-schema.ts","../src/utils/splice-schema.ts","../src/utils/template-schema.ts","../src/utils/template-parser.ts"],"names":["U_HEIGHT_PX","RACK_HEADER_HEIGHT","RACK_WIDTH_PX","HANDLE_EXTENSION_PX","resolveSystemColorMode","colorMode","getReactFlowThemeClassName","className","themeClass","getReactFlowBackgroundColor","getReactFlowWrapperStyle","customStyle","RACK_DEVICE_NODE_TYPES","rackDeviceTypeSet","isRackDeviceNodeType","nodeType","isRackDeviceNode","node","DEFAULT_RACK_FACE_GAP_PX","getRackLayoutMode","data","isSplitFaceRackLayout","getRackFaceGapPx","getRackFaceWidthPx","getRackTotalWidthPx","faceWidth","getRackMountMode","getVisibleFacesForMountMode","mountMode","sharesMountedFace","mountModeA","mountModeB","facesA","face","getRackDeviceXPosition","rackData","deviceData","getRackDeviceBodyWidthPx","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","splitFaceLayout","deviceMountMode","otherDevice","otherUPosition","otherUHeight","newDeviceStart","newDeviceEnd","otherDeviceStart","otherDeviceEnd","otherMountMode","startFrom","u","calculateDevicePositionFromU","deviceHeight","deviceY","updateDeviceUPosition","newUPosition","normalizedPorts","validateAndSnapDevice","currentUPosition","validUPosition","getStatusColor","status","RackNode","selected","id","onViewChange","onRackFaceChange","isDragOver","label","ports","customHeaderText","effectiveWidth","faceGap","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","getFiberPaint","overrides","base","striped","backgroundImage","fiberSolidOrStriped","paint","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","isRibbon","highlight","highlightMaxWidth","baseEdgeStyle","PowerEdge","markerEnd","connectorType","metadata","customStrokeWidth","customStrokeDasharray","customOpacity","strokeWidth","strokeDasharray","renderRibbonSmoothStepEdge","getSmoothStepPath","SmoothStepFiberEdge","props","edgeStyle","ReactFlowSmoothStepEdge","getStepPath","_targetPosition","isHorizontalFirst","midX","midY","renderRibbonStepEdge","pathMatch","StepFiberEdge","_props","ThickCableEdge","_selected","Width","POWER_CONNECTORS","getPowerPortStyle","connector","isHighPower","isGenericAc","width","height","cornerStyle","getConnectorConfig","isHighPowerConnector","getPDUPortType","portIndex","getDeviceConnectorType","deviceName","name","DIRECTIONAL_HANDLE_SUFFIX","normalizeDirectionalHandleId","handleId","isPowerPortType","portType","buildPortHandleId","portBlockName","port","looksLikePowerHandleId","normalized","DISCONNECTED_PORT_COLOR","DISCONNECTED_PORT_BORDER_COLOR","DEFAULT_CONNECTED_PORT_COLOR","FILL_BACKGROUND_SIZE","CONNECTED_CABLE_COLORS","URL_SCHEME_PATTERN","SAFE_DATA_IMAGE_URL_PATTERN","useIsomorphicLayoutEffect","React","normalizeDeviceType","deviceType","isRelativeUrl","url","sanitizeDeviceImageUrl","trimmed","parsedUrl","protocol","toCssUrlValue","isPowerPort","getHandleId","hasAbsolutePosition","resolveCurrentFace","view","rearPorts","frontImageUrl","rearImageUrl","hasFront","hasRear","resolveBackgroundSize","imageFit","stretchToFit","getConnectedPortColor","getPortColor","getPortBlocksSignature","portBlocks","block","portsSignature","position","getBaseHandleStyle","portWidth","portHeight","portColor","borderColor","compactMinSize","getGenericPortDimensions","faceRegionWidth","clampPercent","value","clampNumber","min","max","mapPortSideToPosition","side","inferSideFromAbsolutePercent","xPercent","yPercent","distances","a","b","getCustomHandlePlacement","absoluteCenterYOverridePx","centerX","centerY","offsetPercent","offsetPx","minCenterX","maxCenterX","minCenterY","maxCenterY","rawCenterX","rawCenterY","getDistributedRowCenterX","rowIndex","rowCount","defaultMinCenterX","defaultMaxCenterX","availableSpan","naturalStep","maxGapPx","compactStep","compactSpan","sideInset","getAlternatingTopBottomPlacement","portCount","topRow","topCount","bottomCount","getAlternatingTopStackPlacement","topPaddingPx","rowGapPx","maxTopPx","secondRowTopPx","topPx","getFrontPowerHandlePlacement","powerStyle","topValue","maxTop","getFrontHandlePlacement","rightPadding","leftPx","getRearHandlePlacement","normalizedDeviceType","getHandleRoles","isPower","isConnected","isPatchPanel","DeviceNode","updateNodeInternals","useUpdateNodeInternals","manufacturer","rawPorts","rawRearPorts","rackWidthPx","imagePosition","imageRepeat","effectiveRackWidth","resolvedFace","visibleFaces","currentFace","showSplitBothFaces","rackFaceGapPx","rightFaceOffsetPx","handleLayoutSignature","resolveFaceBackgroundStyle","safeBackgroundImageUrl","frontBackgroundStyle","rearBackgroundStyle","activeBackgroundStyle","rackDeviceWidth","rackDeviceLeft","fullWidthPx","halfWidthPx","isOneUServer","statusColor","deviceContainerStyle","frontHandleIds","resolveRenderedHandleId","computeCompressedTopRowCenterOverrides","portsInBlock","absoluteTopPorts","uniqueRows","maxSpread","preferredGap","gap","spread","averageOriginalCenterY","total","rowCenterByY","rowY","renderPortsFromArray","faceOffsetPx","handles","totalPortsOnFace","shouldLineUpDenseSwitchPortsAgainstTop","portBlock","compressedTopRowOverrides","actualPortWidth","actualPortHeight","useCompactMinSize","baseStyle","defaultPlacement","customPlacement","placement","translatedHandleStyle","renderedHandleId","roles","secondaryHandleStyle","secondaryTitle","renderedHandles","PDU_HEADER_HEIGHT","PDU_BOTTOM_PADDING","PDU_TOP_PADDING","GROUP_GAP_UNITS","inferClosestSideFromPercent","normalizeConnectorType","resolvePortConnectorType","fallback","fromConnector","type","toPduPortGroups","getConnectorSequence","count","_","explicit","buildRenderablePorts","powerPorts","customGroups","connectorSequence","flatIndex","group","fallbackType","buildAutoYPositions","bodyHeight","drawableHeight","units","cursor","maxUnit","step","unit","resolveCustomPlacement","fallbackCenterY","widthPx","handleWidth","handleHeight","resolvedSide","resolvedPosition","getMgmtPortIndex","mgmtUnit","totalPorts","renderMgmtUnit","yCenter","VerticalPDU","heightCm","mgmt_unit","safePowerPorts","heightPx","autoYPositions","mgmtPortIndex","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","handlePosition","reverseColors","fiberIdx","fiberHandleId","connectedEdge","connectedIsRibbon","edgeColor","edgeStriped","fiberPaint","left","top","handleStyle","CableNode","providedFiberCount","cableId","rotation","containerRef","rotationDegrees","innerPaddingTop","primaryText","secondaryText","defaultCableColor","cableColor","getHandlePosition","rotationDeg","renderHandles","baseColor","handleBackground","buttonHandleId","buttonHandleSize","buttonHandleStyle","buttonHandlePosition","containerStyle","contentStyle","MultiTubeCableNode","tubeCount","rawTubeStartIndex","tubes","tubeStartIndex","totalFibers","firstTubeColor","tubeIdx","tubePaint","tubeHandleId","CouplerNode","couplerFiberCount","portLabelsLeft","portLabelsRight","normalizedFiberCount","minWidth","minHeight","totalHandlesHeight","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","calculateMaxChildRight","childNodes","maxRight","dims","childRight","calculateMaxChildBottom","maxBottom","childBottom","getPanelWidth","panelNode","getPanelHeight","getInnerContentWidth","calculateCouplerRightX","couplerWidth","calculateSlotPositionFromY","y","slotHeight","calculateYFromSlotPosition","slot","snapToCouplerPosition","coupler","panel","calculatePanelDimensions","hasTubes","hasTrays","hasCouplers","tubeWidth","contentWidth","sidePadding","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","tube","PatchPanelNode","header","dataWidth","dataHeight","isUpdatingRef","useRef","childNodesRef","filtered","dynamicDimensions","useEffect","currentWidth","currentHeight","widthDiff","heightDiff","panelWidth","panelHeight","headerHeight","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","handle","getEndpointConnectionKind","normalizedHandle","frontBlocks","rearBlocks","handleLc","isStandardNetworkHandle","isCustomPortName","isPowerEndpointHandle","defaultValidateConnection","params","ctx","fiberConnection","sourceKind","targetKind","isPowerConnection","hasPduEndpoint","normalizedSourceHandle","normalizedTargetHandle","sourceHandleAlreadyConnected","targetHandleAlreadyConnected","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","rearHandleAliasSuffix","normalizedHandleId","hasExplicitRearAlias","handleSideMap","createNetworkDiagramStore","initial","options","state","listeners","partial","l","listener","edge","getNodeParentId","legacyParent","getVisibleFaces","parentId","parentRack","hasRearPorts","hasFrontPorts","resolveEndpointVisibility","nodeId","isPowerHandle","isNetworkHandle","targetVisibility","sourceVisibility","useNetworkDiagram","store","subscribe","cb","_state","getSnapshot","useSyncExternalStore","useNodes","useSelectEdgeZIndex","getRackBounds","rackWidth","rackHeight","rackLeft","rackRight","rackTop","rackBottom","isPointInRack","point","bounds","findNearestRack","racks","nearestRack","minDistance","distance","replaceEdge","connection","edgeType","selectEdgeZIndex","findBy","matchOn","existingEdge","edgeFromAddEdge","addEdge","newEdge","zIndex","edgeWithMetadata","countPorts","hasImage","inferRackMountModeFromFaces","nodeData","resolveSplitRackMountModeForDrop","dropRelativeX","explicitMountMode","inferredMountMode","splitMidpointX","isSpliceRibbonMode","spliceNode","NodeWithDataType","children","wrapperRef","setDataTypeRef","element","parent","attempts","createNodeTypes","getDragOverRackId","isSwitchLikeNode","normalizeSwitchPortConnection","sourceHandle","targetHandle","defaultEdgeTypes","MAX_TO_IMAGE_WIDTH","MAX_TO_IMAGE_HEIGHT","MAX_TO_IMAGE_PADDING","MAX_TO_IMAGE_PIXEL_RATIO","clampNumericOption","normalizeToImageOptions","NetworkDiagramInner","initialNodes","initialEdges","externalOnNodesChange","externalOnEdgesChange","debug","onNodeClick","onEdgeClick","externalNodeTypes","externalEdgeTypes","externalOnConnect","externalOnEdgeUpdate","externalIsValidConnection","externalConnectionMode","alignRacksToBottom","reAssignable","onInit","onFlowMethods","showDownloadButton","downloadButtonPosition","downloadButtonText","downloadButtonStyle","useSmoothstepEdgesForTubes","readOnly","interaction","actionPanel","connectOnClick","panOnDrag","panOnScroll","zoomOnScroll","fitViewOptions","validateAndFilterEdges","useCallback","edgesToValidate","nodesForValidation","seenHandles","validEdges","removedEdges","isSpecialHandle","sourceHandleKey","existingSourceEdge","isSourceSpecial","targetHandleKey","existingTargetEdge","isTargetSpecial","isControlled","initialNodesForValidation","initialEdgesRaw","validatedInitialEdges","localStore","storeNodes","storeEdges","reactFlowNodes","useNodesState","reactFlowEdges","setEdges","onEdgesChange","useEdgesState","reactFlowWrapper","isMobile","setIsMobile","checkMobile","isReadOnly","interactionConfig","merged","actionPanelConfig","toObject","setViewport","setReactFlowNodes","setReactFlowEdges","getEdges","fitView","flowToScreenPosition","toPng","nodeObjects","_unused","restOptions","isDownloading","setIsDownloading","onDownload","dataUrl","link","error","dragOverRackId","setDragOverRackId","dragOverRackIdRef","onViewChangeRef","onRackFaceChangeRef","onViewChangeStable","onRackFaceChangeStable","rackId","getDragOverRackIdStable","nodeTypesRef","mergedEdgeTypes","latestNodesRef","latestEdgesRef","validated","rackBottoms","r","minBottom","baselineBottom","nextNodes","currentBottom","delta","nodesMapRef","map","getNodeById","getParentRackNode","parentNode","isSplitFaceRackNode","isSplitFaceRackDeviceNode","isPatchPanelDeviceNode","commitNodes","commitEdges","nextEdges","getAbsoluteNodePosition","x","seenParents","getRackDropPoint","absolute","deriveFiberColorFromSource","sourceNodeId","inputEdges","inputColor","fiberNumStr","fiberNum","tubeNumStr","tubeNum","edgesZIndexRef","eds","hasChanges","updated","newZIndex","updatedNodes","parentPanel","parentTray","originalNode","handleNodesChange","changes","holderPositionUpdates","uPositionUpdates","parentExtentIds","updatedChanges","change","parentClosure","snappedResult","applyNodeChanges","updatedNode","handleNodeDragStart","_event","handleNodeDrag","_nodes","dropPoint","nextRackId","currentRackId","handleNodeDragStop","absolutePosition","currentNodes","relativeToRack","baseNode","splitFaceRack","nextMountMode","initialDeviceX","nextView","candidateNode","nodesForSnapping","snapped","currentNode","handleIsValidConnection","handleConnect","normalizedParams","initialValidation","isPduSource","sourceIsPowerEndpoint","targetIsPowerEndpoint","sourceNodeData","isSwitchSource","looksLikePowerTarget","looksLikeNetworkTarget","looksLikeNetworkSource","isSwitchTarget","isPduTarget","looksLikePowerSource","isTubeToCable","isCableToTube","isTubeConnection","isButtonHandleConnection","edgeData","isRibbonSpliceTarget","isRibbonSpliceSource","targetSpliceData","sourceSpliceData","edgesToRemove","existingSpliceEdge","newEdgeId","newEdges","validation","sourceHandleAlreadyUsed","targetHandleAlreadyUsed","isSpecialHandleForReplacement","isSourceSpecialForReplacement","isTargetSpecialForReplacement","edgeToAdd","setAnimatingEdges","prev","handleEdgeUpdate","oldEdge","newConnection","normalizedConnection","hasHandleOccupancyConflict","matchesSource","matchesTarget","handleNodeClick","event","isCommandClick","selectedTarget","setSelectedNode","setSelectedEdges","nds","shouldSelect","currentView","handleNodeDoubleClick","handleEdgeClick","handlePaneClick","selectedNode","animatingEdges","useOnSelectionChange","selectedEdges","handleKeyDown","deletableEdges","edgeIdsToDelete","remainingEdges","handleConnectStart","handleType","handleConnectEnd","toggleSelectedFace","deRackSelectedDevice","edgesWithAnimation","nodesMap","sourceSide","targetSide","resolveVisibleFaces","sourceVisibleFaces","targetVisibleFaces","sourceIsPatchPanel","targetIsPatchPanel","sourceHasMismatchedSide","targetHasMismatchedSide","shouldHide","nextStyle","rest","selectedNodeForActions","selectedActionButtons","supportsRearToggle","showRearToggle","showDeRack","actionPanelPosition","wrapperRect","nodeWidth","nodeHeight","topCenterAnchor","bottomCenterAnchor","flowClassName","wrapperStyle","ReactFlow","filteredChanges","edgeToRemove","applyEdgeChanges","Background","Controls","MiniMap","Panel","NetworkDiagram","ReactFlowProvider","DiagramErrorBoundary","Component","errorInfo","buildFibreFlowCableLayout","cable","rowHeight","tubeGap","rows","tubeLabels","kind","fiberStartIndex","currentY","tubeOffset","tubeColor","fiberOffset","fiberIndex","isRecord","isFibreFlowNode","isFibreFlowEdgeType","hasEdgeEndpoints","inferFibreFlowEdgeType","normalizeFibreFlowEdges","previousEdges","previousById","previous","handleIdForEndpoint","endpoint","getFiberColorFromEndpoint","isStripedEndpoint","formatDistanceLabel","distanceMeters","distanceLabel","buildFibreFlowStripeDasharray","needsStripeFirstHalf","needsStripeSecondHalf","firstHalfDashPattern","secondHalfDashPattern","halfLength","approximatePathLength","FibreFlowEdge","lossText","labelText","sourceColor","targetColor","sourceStriped","targetStriped","isHighlighted","isDimmed","circuitId","circuitLabel","showCircuitId","needsGradient","dx","dy","totalDistance","labelDx","labelDy","labelDistance","gradientStopPercent","gradientId","needsStripeFull","dashGapPair","numPairsWithBuffer","secondHalfNumPairs","hasCircuitId","labelWidth","labelHeight","FibreFlowCableLinkEdge","FibreFlowCableNode","columnWidth","showTubeLabels","showFiberNumbers","layout","isLightMode","jacketWidth","labelOffset","panelInset","jacketColor","effectiveShowTubeLabels","panelLeft","panelRight","cableRunHandleStyle","tubeRows","row","tubeTop","tubeBottom","tubeHeight","nextTube","hasGapAfter","_tubeIdx","numberPosition","FibreFlowClosureNode","buildFlowNodes","closures","closureGap","cableColumnWidth","spliceAreaWidth","closure","leftLayout","rightLayout","bodyWidth","closureId","leftCableId","rightCableId","headerLabel","leftOffsetY","rightOffsetY","buildFlowEdges","circuits","highlightedCircuitId","circuitColorMap","circuitLabelMap","lastCableById","circuit","circuitColor","FibreFlowMapInner","layoutNodes","layoutEdges","getHandleFiberInfo","match","isValidConnection","isSourceFiberHandle","isTargetFiberHandle","onConnect","isCableRun","isFiberHandle","sourceIsFiber","targetIsFiber","usesHandle","sourceInfo","targetInfo","pruned","sourceTaken","targetTaken","onEdgeUpdate","withoutOld","handleEdgesChange","nodeTypes","edgeTypes","ConnectionMode","FibreFlowMap","FibreCableWithTubesExpanded","showCableLabel","cableLayout","portSize","portInset","innerPortX","tubeLabelX","useTubeLabels","numberLeft","inventoryRackToNetworkNode","inventoryDeviceToNetworkNode","inventoryCableToNetworkEdge","getDeviceId","term","dev","termADeviceId","termBDeviceId","inventoryToNetworkDiagram","generateLayout","rackNodes","deviceNodes","otherNodes","resolveDeviceNodeId","DEFAULT_INTERFACE_GROUP","DEFAULT_MANAGEMENT_GROUP","DEFAULT_POWER_GROUP","toNonEmptyString","toNumber","parsed","normalizePortFace","getInterfaceCustomFields","iface","getNestedLayoutHints","resolvePortFaceHint","mappedFace","customFields","nestedLayout","resolvePortGroupHint","mappedGroup","explicitGroup","resolveConnectorTypeHint","rawType","mappedConnectorType","normalizePortType","normalizeCableType","parsePortPosition","sideRaw","extractMappedPosition","mappedPort","includePortPositions","candidates","candidate","defaultMapInterfaceToPort","sortInterfaces","interfaces","aPosition","bPosition","upsertPortBlock","existing","created","buildInterfacePortBlocks","mapInterfaceToPort","front","rear","targetFace","groupName","netboxRackToNetworkNode","netboxDeviceToNetworkNode","netboxCableToNetworkEdge","netboxToNetworkDiagram","deviceNodeIdByName","deviceNode","sourceId","targetId","calculateUPositions","devices","_rackHeight","usedPositions","d","validatePlacements","items","checkOutOfBounds","checkConflicts","conflicts","outOfBounds","item","boundsCheck","itemA","j","itemB","conflictCheck","DevicePlacementError","deviceId","conflictWith","validateRackDevicePlacements","_options","deviceA","deviceB","deviceAStart","deviceAEnd","deviceBStart","deviceBEnd","createDeviceNode","deviceTypeMapping","createRackNode","buildNodesFromRackConfig","conflictPolicy","errors","conflict","bound","rackNode","adjustedDevice","createRackConfigFromNodes","addDeviceToRack","removeDeviceFromRack","SplicePlacementError","trayId","spliceId","holder","validateSplicePlacements","spliceA","spliceB","createSpliceNode","createTrayNode","buildNodesFromSpliceConfig","spliceNodes","trayNode","resolvedHolder","placeholderSplice","allNodesForConflictCheck","adjustedSplice","createSpliceConfigFromNodes","trayNodes","splices","updateSpliceHolderPosition","newHolder","addSpliceToTray","removeSpliceFromTray","TEMPLATE_SCHEMA_VERSION","toStr","v","toFiniteNumber","normalizeConnector","raw","s","inferConnectorFromType","normalizeRole","inferMountClass","normalizeWidth","generatePortId","blockIndex","safeLabel","generateSlug","model","stageIngest","issues","role","slug","normalizedLinks","normalizePortBlock","rawBlock","rawPort","rawConnector","hasPosition","stageNormalize","ingested","mountClass","frontPortBlocks","rearPortBlocks","addFacePrefixesIfNeeded","frontFace","rearFace","frontNames","rearNames","overlapping","stageEnrich","countFacePorts","stageValidate","enriched","allPorts","idCounts","rawFrontCount","rawRearCount","parsedFrontCount","parsedRearCount","allPortIds","frontPortIds","rearPortIds","stageExport","links","source","parseNetboxTemplate","report","countTemplateFacePorts","validateRenderFidelity","template","renderedFrontHandleCount","renderedRearHandleCount","expectedFront","expectedRear"],"mappings":"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","file":"index.js","sourcesContent":["// Shared layout constants for racks/devices\n\nexport const U_HEIGHT_PX = 20; // 20px per U\nexport const RACK_HEADER_HEIGHT = 60; // Fixed rack header height in px\nexport const RACK_WIDTH_PX = 300; // Fixed rack width in px\n\n/**\n * Handle extension in pixels - handles extend this many pixels outside nodes\n * Used in dimension calculations for panels and closures\n */\nexport const HANDLE_EXTENSION_PX = 5;\n\n","/**\n * Shared React Flow theming utilities\n * Ensures consistent styling across all React Flow components in the library\n */\n\nexport type ColorMode = 'light' | 'dark' | 'system';\n\n// Re-export for convenience\nexport type { ColorMode as ReactFlowColorMode };\n\n/**\n * Resolve system color mode to light or dark based on system preference\n */\nfunction resolveSystemColorMode(colorMode: ColorMode): 'light' | 'dark' {\n if (colorMode === 'system') {\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';\n }\n // Default to dark if we can't detect system preference\n return 'dark';\n }\n return colorMode;\n}\n\n/**\n * Get the React Flow theme class name based on color mode\n */\nexport function getReactFlowThemeClassName(colorMode: ColorMode, className?: string): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n const themeClass = resolvedMode === 'light' ? 'react-flow-light' : 'react-flow-dark';\n return className ? `${themeClass} ${className}` : themeClass;\n}\n\n/**\n * Get the background color for React Flow Background component\n */\nexport function getReactFlowBackgroundColor(colorMode: ColorMode): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n return resolvedMode === 'light' ? '#e5e5e5' : '#2a2a2a';\n}\n\n/**\n * Get the wrapper div style for React Flow components\n * Provides consistent container styling\n */\nexport function getReactFlowWrapperStyle(\n colorMode: ColorMode,\n customStyle?: React.CSSProperties\n): React.CSSProperties {\n return {\n width: '100%',\n height: '100%',\n ...customStyle,\n };\n}\n\n/**\n * Get the background color for React Flow Background component with custom opacity\n */\nexport function getReactFlowBackgroundColorWithOpacity(colorMode: ColorMode, opacity: number = 0.08): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n const baseColor = resolvedMode === 'light' ? '15, 23, 42' : '148, 163, 184';\n return `rgba(${baseColor}, ${opacity})`;\n}\n","/**\n * Node types that represent rack-mounted devices with U-position behavior.\n */\nexport const RACK_DEVICE_NODE_TYPES = ['device', 'server', 'switch', 'router'] as const;\n\nexport type RackDeviceNodeType = (typeof RACK_DEVICE_NODE_TYPES)[number];\n\nconst rackDeviceTypeSet = new Set<string>(RACK_DEVICE_NODE_TYPES);\n\n/**\n * Check if a node type is rack-mountable (U-positioned) device type.\n */\nexport function isRackDeviceNodeType(nodeType: string | undefined): nodeType is RackDeviceNodeType {\n return typeof nodeType === 'string' && rackDeviceTypeSet.has(nodeType);\n}\n\n/**\n * Check if a node is a rack-mountable (U-positioned) device.\n */\nexport function isRackDeviceNode(node: { type?: string } | null | undefined): node is { type: RackDeviceNodeType } {\n return !!node && isRackDeviceNodeType(node.type);\n}\n","import type { DeviceView, RackLayoutMode, RackMountMode } from '../types';\nimport { RACK_WIDTH_PX } from './constants';\n\ninterface RackLayoutData {\n rackLayout?: RackLayoutMode;\n rackFaceGapPx?: number;\n rackWidthPx?: number;\n}\n\ninterface RackMountData {\n mountMode?: RackMountMode;\n}\n\nexport const DEFAULT_RACK_FACE_GAP_PX = 24;\n\nexport function getRackLayoutMode(data: RackLayoutData | undefined): RackLayoutMode {\n return data?.rackLayout === 'split-face' ? 'split-face' : 'single-face';\n}\n\nexport function isSplitFaceRackLayout(data: RackLayoutData | undefined): boolean {\n return getRackLayoutMode(data) === 'split-face';\n}\n\nexport function getRackFaceGapPx(data: RackLayoutData | undefined): number {\n if (typeof data?.rackFaceGapPx === 'number' && Number.isFinite(data.rackFaceGapPx) && data.rackFaceGapPx >= 0) {\n return data.rackFaceGapPx;\n }\n return DEFAULT_RACK_FACE_GAP_PX;\n}\n\nexport function getRackFaceWidthPx(data: RackLayoutData | undefined): number {\n return data?.rackWidthPx || RACK_WIDTH_PX;\n}\n\nexport function getRackTotalWidthPx(data: RackLayoutData | undefined): number {\n const faceWidth = getRackFaceWidthPx(data);\n if (!isSplitFaceRackLayout(data)) {\n return faceWidth;\n }\n return faceWidth * 2 + getRackFaceGapPx(data);\n}\n\nexport function getRackMountMode(data: RackMountData | undefined): RackMountMode {\n if (data?.mountMode === 'front' || data?.mountMode === 'rear' || data?.mountMode === 'both') {\n return data.mountMode;\n }\n return 'both';\n}\n\nexport function getVisibleFacesForMountMode(mountMode: RackMountMode): DeviceView[] {\n if (mountMode === 'front') {\n return ['front'];\n }\n if (mountMode === 'rear') {\n return ['rear'];\n }\n return ['front', 'rear'];\n}\n\nexport function sharesMountedFace(\n mountModeA: RackMountMode,\n mountModeB: RackMountMode\n): boolean {\n const facesA = new Set(getVisibleFacesForMountMode(mountModeA));\n const facesB = getVisibleFacesForMountMode(mountModeB);\n return facesB.some((face) => facesA.has(face));\n}\n\nexport function getRackDeviceXPosition(\n rackData: RackLayoutData | undefined,\n deviceData: RackMountData | undefined\n): number {\n if (!isSplitFaceRackLayout(rackData)) {\n return 0;\n }\n const mountMode = getRackMountMode(deviceData);\n // Split-face orientation: rear on left, front on right.\n if (mountMode === 'front') {\n return getRackFaceWidthPx(rackData) + getRackFaceGapPx(rackData);\n }\n return 0;\n}\n\nexport function getRackDeviceBodyWidthPx(\n rackData: RackLayoutData | undefined,\n deviceData: RackMountData | undefined\n): number {\n if (!isSplitFaceRackLayout(rackData)) {\n return getRackFaceWidthPx(rackData);\n }\n const mountMode = getRackMountMode(deviceData);\n if (mountMode === 'both') {\n return getRackTotalWidthPx(rackData);\n }\n return getRackFaceWidthPx(rackData);\n}\n","import { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\nimport { isRackDeviceNodeType } from './rack-device-types';\nimport {\n getRackDeviceXPosition,\n getRackMountMode,\n isSplitFaceRackLayout,\n sharesMountedFace,\n} from './rack-layout';\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: getRackDeviceXPosition(rack.data, device.data),\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 isRackDeviceNodeType(node.type) &&\n node.parentId === rack.id && \n node.id !== device.id\n );\n const splitFaceLayout = isSplitFaceRackLayout(rack.data);\n const deviceMountMode = getRackMountMode(device.data);\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 if (splitFaceLayout) {\n const otherMountMode = getRackMountMode(otherDevice.data);\n if (!sharesMountedFace(deviceMountMode, otherMountMode)) {\n continue;\n }\n }\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 deviceData?: Pick<NetworkNode['data'], 'mountMode'>\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: getRackDeviceXPosition(rack.data, deviceData), // Align with active rack face (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<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'>,\n rack: NetworkNode,\n newUPosition: number\n): NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'> => {\n const deviceHeight = device.data.uHeight || 1;\n const newPosition = calculateDevicePositionFromU(rack, newUPosition, deviceHeight, device.data);\n const normalizedPorts = Array.isArray(device.data.ports) ? device.data.ports : undefined;\n \n return {\n ...device,\n position: newPosition,\n data: {\n ...device.data,\n ports: normalizedPorts,\n uPosition: newUPosition,\n },\n };\n};\n\n/**\n * Validate and snap device to valid U position\n */\nexport const validateAndSnapDevice = (\n device: NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'>,\n rack: NetworkNode\n): NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'> => {\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 '#ef4444';\n case 'maintenance':\n return '#f59e0b';\n default:\n return '#6b7280';\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 } from '../utils/constants';\nimport { getRackUNumberingDirection, convertUPositionForDirection } from '../utils/u-positioning';\nimport { getStatusColor } from '../utils/status-colors';\nimport {\n getRackFaceGapPx,\n getRackFaceWidthPx,\n getRackTotalWidthPx,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\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\n/**\n * Rack visualization component with U positioning support.\n * \n * Displays a 19\" rack with configurable height, front/rear view switching,\n * and support for mounting devices at specific U positions.\n * \n * @example\n * ```tsx\n * {\n * id: 'rack-1',\n * type: 'rack',\n * position: { x: 100, y: 100 },\n * data: {\n * label: 'Main Rack',\n * uHeight: 42,\n * status: 'active'\n * }\n * }\n * ```\n * \n * @public\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 splitFaceLayout = isSplitFaceRackLayout(data);\n const effectiveWidth = getRackTotalWidthPx(data);\n const faceWidth = getRackFaceWidthPx(data);\n const faceGap = getRackFaceGapPx(data);\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 if (splitFaceLayout) {\n return;\n }\n\n const next = face === 'front' ? 'rear' : 'front';\n \n if (onRackFaceChange) {\n onRackFaceChange(id, next);\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 • {splitFaceLayout ? 'rear|front' : 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 {!splitFaceLayout && (\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 )}\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 {splitFaceLayout && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n display: 'flex',\n }}\n >\n <div\n style={{\n width: `${faceWidth}px`,\n borderRight: '1px dashed rgba(156,163,175,0.35)',\n background: 'rgba(17,24,39,0.15)',\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n paddingTop: '4px',\n fontSize: '8px',\n color: '#9ca3af',\n fontWeight: 'bold',\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Rear\n </div>\n <div style={{ width: `${faceGap}px` }} />\n <div\n style={{\n width: `${faceWidth}px`,\n borderLeft: '1px dashed rgba(156,163,175,0.35)',\n background: 'rgba(17,24,39,0.25)',\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n paddingTop: '4px',\n fontSize: '8px',\n color: '#9ca3af',\n fontWeight: 'bold',\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Front\n </div>\n </div>\n )}\n </div>\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 * Fiber paint metadata used by handle and edge rendering.\n * @public\n */\nexport interface FiberPaint {\n base: string;\n striped: boolean;\n backgroundImage?: string;\n}\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 * Resolve the visual paint for a fiber (base + optional stripe pattern).\n * By default this follows TIA-598 logic: 1-12 solid, 13-24 striped.\n * @param id - Fiber color ID (1-24)\n * @param overrides - Optional visual overrides\n * @returns Paint metadata\n * @public\n */\nexport function getFiberPaint(\n id: FiberColorId | number,\n overrides?: { base?: string; striped?: boolean }\n): FiberPaint {\n const base = overrides?.base ?? baseColorFor(id);\n const striped = overrides?.striped ?? isStriped(id);\n const backgroundImage = striped\n ? `repeating-linear-gradient(45deg, ${base} 0 6px, #000 6px 9px)`\n : undefined;\n\n return { base, striped, backgroundImage };\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 paint = getFiberPaint(id);\n if (paint.backgroundImage) {\n return {\n background: paint.base,\n backgroundImage: paint.backgroundImage,\n };\n }\n return { background: paint.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}\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\n/**\n * Fiber edge component for connecting fiber ports between nodes.\n * \n * Supports both single fiber connections with color coding and ribbon fiber\n * connections (6-12 fibers) with parallel stripe visualization.\n * \n * @example\n * ```tsx\n * {\n * id: 'edge-1',\n * source: 'node-1',\n * target: 'node-2',\n * sourceHandle: 'fiber-1',\n * targetHandle: 'fiber-2',\n * type: 'fiber',\n * data: {\n * kind: 'fiber',\n * ribbonFiberIds: [1, 2, 3, 4, 5, 6] // For ribbon mode\n * }\n * }\n * ```\n * \n * @public\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 const metadata = (data?.metadata ?? {}) as Record<string, unknown>;\n const customStrokeWidth = typeof data?.powerStrokeWidth === 'number'\n ? data.powerStrokeWidth\n : (typeof metadata.strokeWidth === 'number' ? metadata.strokeWidth : undefined);\n const customStrokeDasharray = typeof data?.powerStrokeDasharray === 'string'\n ? data.powerStrokeDasharray\n : (typeof metadata.strokeDasharray === 'string' ? metadata.strokeDasharray : undefined);\n const customOpacity = typeof data?.powerOpacity === 'number'\n ? data.powerOpacity\n : (typeof metadata.opacity === 'number' ? metadata.opacity : undefined);\n\n // Different styling for different connector types\n const getEdgeStyle = () => {\n const connectorStrokeWidth = connectorType === 'C19' ? 5 : 3;\n const strokeWidth = customStrokeWidth ?? connectorStrokeWidth;\n const strokeDasharray = customStrokeDasharray ?? (connectorType === 'C19' ? 'none' : '6,3');\n const baseStyle = {\n stroke: data?.color || '#f59e0b',\n strokeWidth,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n ...(customOpacity !== undefined ? { opacity: customOpacity } : {}),\n };\n return {\n ...baseStyle,\n strokeDasharray,\n ...style, // This includes zIndex from React Flow\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 */\nimport type {\n Connection,\n Edge as ReactFlowEdge,\n EdgeTypes,\n Node as ReactFlowNode,\n NodeTypes,\n ConnectionMode,\n FitViewOptions,\n ReactFlowInstance,\n Viewport,\n} from 'reactflow';\nimport type { FibreFlowCable } from './fibre-flow';\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\n/**\n * Cable types used for connected network ports.\n * @public\n */\nexport type PortCableType =\n | 'smf'\n | 'cat6'\n | 'om3'\n | 'om4'\n | 'om5'\n | 'cat5e'\n | 'cat6a'\n | 'cat7'\n | 'fiber'\n | 'ethernet';\n\n/**\n * Device image fit options.\n *\n * Values mirror object-fit terms for API ergonomics and are mapped to valid\n * background-size values by renderers where needed.\n *\n * @public\n */\nexport type DeviceImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n\n/**\n * Device image repeat options.\n * @public\n */\nexport type DeviceImageRepeat = 'no-repeat' | 'repeat' | 'repeat-x' | 'repeat-y';\n\n/**\n * Shared image configuration for rack-mounted devices and device nodes.\n * @public\n */\nexport interface DeviceImageOptions {\n /** Optional front image URL for device background (PNG, SVG, JPEG, etc.) */\n frontImageUrl?: string;\n /** Optional rear image URL for device background (PNG, SVG, JPEG, etc.) */\n rearImageUrl?: string;\n /** Optional attribution URL for front image (e.g. source/license link) */\n frontImageAttribution?: string;\n /** Optional attribution URL for rear image (e.g. source/license link) */\n rearImageAttribution?: string;\n /** Optional background sizing for device images */\n imageFit?: DeviceImageFit;\n /** Optional background position for device images */\n imagePosition?: string;\n /** Optional background repeat for device images */\n imageRepeat?: DeviceImageRepeat;\n /** When true, stretch device image to fill the device bounds (overrides imageFit) */\n stretchToFit?: boolean;\n}\n\n/**\n * Explicit handle placement for a device/PDU port.\n * @public\n */\nexport interface PortPosition {\n /** Handle side on the node */\n side?: 'top' | 'right' | 'bottom' | 'left';\n /** Side offset as percentage (0-100) */\n offsetPercent?: number;\n /** Side offset in pixels */\n offsetPx?: number;\n /** Absolute X position as percentage (0-100) */\n xPercent?: number;\n /** Absolute Y position as percentage (0-100) */\n yPercent?: number;\n}\n\nexport interface Port {\n /** Stable handle identifier override (defaults to `label`) */\n id?: string;\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?: PortCableType;\n /** Optional power connector type for rendering (mainly for PDU ports) */\n connectorType?: 'C13' | 'C14' | 'C19' | 'C20';\n /** Optional explicit handle placement */\n position?: PortPosition;\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 | 'fibre-flow-cable'\n | 'fibre-flow-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 * Rack rendering layout modes.\n * @public\n */\nexport type RackLayoutMode = 'single-face' | 'split-face';\n\n/**\n * Rack mounting behavior for a device.\n * @public\n */\nexport type RackMountMode = 'front' | 'rear' | 'both';\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 * Shared node data fields available across node types.\n * Specific node kinds can narrow these fields via `NetworkNodeDataByType`.\n * @public\n */\nexport interface NetworkNodeDataBase extends DeviceImageOptions {\n /** Display label for the node */\n label: string;\n /** Current status of the node/device */\n status?: DeviceStatus | string;\n /** Port configurations for device-like nodes */\n ports?: PortBlock[] | number;\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** List of connected node IDs */\n connections?: string[];\n /** NetBox integration ID */\n netboxId?: number | string;\n /** NetBox object type */\n netboxType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Inventory integration ID */\n inventoryId?: number | string;\n /** Inventory object type */\n inventoryType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Rack height in U units */\n uHeight?: number;\n /** Device position within rack in U units */\n uPosition?: number;\n /** Current front/rear view orientation */\n view?: DeviceView;\n /** Rack face orientation */\n face?: DeviceView;\n /** Rack rendering layout mode */\n rackLayout?: RackLayoutMode;\n /** Gap in pixels between front and rear faces in split-face mode */\n rackFaceGapPx?: number;\n /** Device mount behavior within a rack */\n mountMode?: RackMountMode;\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 | number;\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 /** Optional explicit PDU connector sequence */\n portTypes?: Array<'C13' | 'C19'>;\n /** Optional grouped PDU ports (supports custom positions/types) */\n pduPortGroups?: PortBlock[];\n /** Vertical PDU width in pixels */\n widthPx?: number;\n /** Optional management unit position for vertical PDUs */\n mgmt_unit?: 'top' | 'middle' | 'bottom';\n /** U numbering direction for rack nodes */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack nodes */\n customHeaderText?: string;\n /** Rack UI marker visibility */\n showUMarkers?: boolean;\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 /** Splice mode */\n mode?: 'single' | 'ribbon';\n /** Legacy ribbon flag */\n ribbon?: boolean;\n /** Ribbon fiber IDs */\n ribbonFiberIds?: 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 panel-like container nodes */\n panelWidth?: number;\n /** Height override for panel-like container nodes */\n panelHeight?: number;\n /** Width override for closure nodes */\n closureWidth?: number;\n /** Height override for closure nodes */\n closureHeight?: 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 /** Number of trays for closure nodes */\n trayCount?: 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 /** Tube index (1-based) */\n tubeIndex?: number;\n /** Tube count for multi-tube cables */\n tubeCount?: number;\n /** Tube start index for multi-tube cables */\n tubeStartIndex?: number;\n /** Number of fibers per tube */\n fibersPerTube?: number;\n /** Total fiber count for cables */\n fiberCount?: number;\n /** Cable identifier */\n cableId?: string;\n /** Primary node color override */\n color?: string;\n /** Rotation in degrees for rotatable nodes */\n rotation?: number;\n /** Tube handle orientation */\n startOn?: 'left-center' | 'left' | 'right';\n /** Rack metadata for integrations */\n facilityId?: string | number | null;\n /** Rack serial metadata */\n serial?: string | null;\n /** Asset tag metadata */\n assetTag?: string | null;\n /** Site metadata */\n site?: string;\n /** Tenant metadata */\n tenant?: string;\n /** Primary IPv4 metadata */\n primaryIp4?: string;\n /** Primary IPv6 metadata */\n primaryIp6?: string;\n /** Rack name metadata */\n rack?: string | number | null;\n /** Optional arrays used by inventory/netbox transforms */\n racks?: unknown[];\n devices?: unknown[];\n cables?: unknown[];\n /** UI color mode metadata */\n colorMode?: 'light' | 'dark' | 'system';\n /** Generic dimensions used by some helpers */\n height?: number;\n headerHeight?: number;\n /** Optional precomputed map for handle-to-face resolution */\n handleSideMap?: Record<string, DeviceView>;\n /** Additional extension metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Rack node data.\n * @public\n */\nexport interface RackNodeData extends NetworkNodeDataBase {\n ports?: number | PortBlock[];\n}\n\n/**\n * Device-like node data (servers/switches/routers/generic device).\n * @public\n */\nexport interface DeviceNodeData extends NetworkNodeDataBase {\n ports?: PortBlock[] | number;\n}\n\n/**\n * Fibre flow cable node data.\n * @public\n */\nexport interface FibreFlowCableNodeData extends NetworkNodeDataBase {\n cable: FibreFlowCable;\n side: 'left' | 'right';\n rowHeight: number;\n columnWidth: number;\n showTubeLabels: boolean;\n showFiberNumbers: boolean;\n layout: unknown;\n colorMode?: 'dark' | 'light';\n}\n\n/**\n * Fibre flow closure node data.\n * @public\n */\nexport interface FibreFlowClosureNodeData extends NetworkNodeDataBase {\n width?: number;\n height?: number;\n headerHeight?: number;\n colorMode?: 'dark' | 'light';\n}\n\n/**\n * Mapping from node type to corresponding data type.\n * @public\n */\nexport interface NetworkNodeDataByType {\n rack: RackNodeData;\n switch: DeviceNodeData;\n router: DeviceNodeData;\n server: DeviceNodeData;\n fiber: NetworkNodeDataBase;\n 'patch-panel': NetworkNodeDataBase;\n device: DeviceNodeData;\n 'vertical-pdu': NetworkNodeDataBase;\n splice: NetworkNodeDataBase;\n 'splice-tray': NetworkNodeDataBase;\n tube: NetworkNodeDataBase;\n cable: NetworkNodeDataBase;\n 'multi-tube-cable': NetworkNodeDataBase;\n coupler: NetworkNodeDataBase;\n closure: NetworkNodeDataBase;\n 'fibre-split': NetworkNodeDataBase;\n 'fibre-flow-cable': FibreFlowCableNodeData;\n 'fibre-flow-closure': FibreFlowClosureNodeData;\n}\n\n/**\n * Union of all node data variants.\n * @public\n */\nexport type NetworkNodeData = NetworkNodeDataByType[NetworkNodeType];\n\n/**\n * Network node structure with data discriminated by `type`.\n * @public\n */\nexport type NetworkNode<\n TType extends NetworkNodeType = NetworkNodeType,\n TExtra = unknown\n> = TType extends NetworkNodeType\n ? ReactFlowNode<NetworkNodeDataByType[TType] & TExtra, TType> & {\n /** Type of network node */\n type: TType;\n /** Node data and configuration */\n data: NetworkNodeDataByType[TType] & TExtra;\n }\n : never;\n\n/**\n * Network edge types\n * @public\n */\nexport type NetworkEdgeType =\n | 'fiber'\n | 'ethernet'\n | 'power'\n | 'smoothstep'\n | 'step'\n | 'thick-cable'\n | 'fibre-flow'\n | 'fibre-flow-link';\n\n/**\n * Edge data payload.\n * @public\n */\nexport interface NetworkEdgeData {\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 /** Legacy striped edge flag */\n striped?: boolean;\n /** Cable type metadata used by demos/helpers */\n cableType?: PortCableType;\n /** NetBox integration metadata */\n netboxId?: number | string;\n netboxType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Inventory integration metadata */\n inventoryId?: number | string;\n inventoryType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Status metadata */\n status?: string;\n /** Endpoint metadata */\n terminationA?: string;\n terminationB?: string;\n /** Optional display label for the edge */\n label?: string;\n /** Optional opacity for styling (0–1) */\n opacity?: number;\n /** Optional power edge stroke width override */\n powerStrokeWidth?: number;\n /** Optional power edge stroke dasharray override */\n powerStrokeDasharray?: string;\n /** Optional power edge opacity override (0–1) */\n powerOpacity?: number;\n /** Additional extension metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Network edge data structure\n * @public\n */\nexport type NetworkEdge<TData extends NetworkEdgeData = NetworkEdgeData> = {\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?: TData;\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 /** Rack rendering layout mode */\n rackLayout?: RackLayoutMode;\n /** Gap in pixels between front and rear faces in split-face mode */\n rackFaceGapPx?: number;\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 extends DeviceImageOptions {\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 mount behavior within a rack */\n mountMode?: RackMountMode;\n /** Device role in network */\n role?: string;\n /** Current status of the device */\n status?: DeviceStatus | 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 * Fine-grained interaction controls for network diagrams.\n * @public\n */\nexport interface NetworkDiagramInteractionOptions {\n /** Enable node dragging. */\n nodesDraggable?: boolean;\n /** Enable creating connections from node handles. */\n nodesConnectable?: boolean;\n /** Enable selecting nodes/edges. */\n elementsSelectable?: boolean;\n /** Enable keyboard/mouse focus on edges. */\n edgesFocusable?: boolean;\n /** Enable reconnecting existing edges. */\n edgesReconnectable?: boolean;\n /** Enable click-to-connect behavior on handles. */\n connectOnClick?: boolean;\n /** Enable panning by dragging the canvas. */\n panOnDrag?: boolean;\n /** Enable panning by scrolling. */\n panOnScroll?: boolean;\n /** Enable zoom via mouse wheel/trackpad scroll. */\n zoomOnScroll?: boolean;\n /** Enable pinch-zoom gestures. */\n zoomOnPinch?: boolean;\n /** Enable zoom on double click. */\n zoomOnDoubleClick?: boolean;\n /** Enable deleting selected edges with keyboard keys. */\n allowKeyboardDelete?: boolean;\n /** Show or hide the built-in React Flow controls widget. */\n showControls?: boolean;\n /** Show or hide the minimap. */\n showMiniMap?: boolean;\n /** Show or hide the interactive lock/unlock button in controls. */\n showInteractiveControl?: boolean;\n}\n\n/**\n * Selection action panel options rendered above selected racks/devices.\n * @public\n */\nexport interface NetworkDiagramActionPanelOptions {\n /** Enable or disable the floating action panel entirely. Defaults to true. */\n enabled?: boolean;\n /** Show or hide the front/rear toggle button. Defaults to true. */\n showRearToggle?: boolean;\n /** Show or hide the De-rack button for rack-mounted devices. Defaults to true. */\n showDeRack?: boolean;\n}\n\n/**\n * Serializable flow snapshot payload for save/restore helpers.\n * @public\n */\nexport interface NetworkDiagramFlowObject {\n /** Snapshot nodes */\n nodes: NetworkNode[];\n /** Snapshot edges */\n edges: NetworkEdge[];\n /** Optional viewport state */\n viewport?: Viewport;\n}\n\n/**\n * Options for exported diagram images.\n * @public\n */\nexport interface NetworkDiagramToImageOptions {\n /** Export width in px (clamped to 1-8192). */\n width?: number;\n /** Export height in px (clamped to 1-8192). */\n height?: number;\n backgroundColor?: string;\n /** Export padding in px (clamped to 0-2048). */\n padding?: number;\n /** Device pixel ratio multiplier (clamped to 0.1-4). */\n pixelRatio?: number;\n /** JPEG/WebP quality (clamped to 0-1 when used). */\n quality?: number;\n filter?: (domNode: HTMLElement) => boolean;\n}\n\n/**\n * Fit-view options that support targeting node IDs directly.\n * @public\n */\nexport interface NetworkDiagramFitViewOptions extends Omit<FitViewOptions, 'nodes'> {\n /** Optional node IDs to fit */\n nodes?: string[];\n}\n\n/**\n * Exposed methods for save/restore and export integrations.\n * @public\n */\nexport interface NetworkDiagramFlowMethods {\n toObject: () => NetworkDiagramFlowObject;\n setViewport: (viewport: Viewport) => void;\n setNodes: (nodes: NetworkNode[]) => void;\n setEdges: (edges: NetworkEdge[]) => void;\n toImage: (options?: NetworkDiagramToImageOptions) => Promise<string>;\n getNodes: () => NetworkNode[];\n getEdges: () => NetworkEdge[];\n fitView: (options?: NetworkDiagramFitViewOptions) => void;\n}\n\n/**\n * Store contract accepted by `NetworkDiagram`.\n * @public\n */\nexport interface NetworkDiagramStoreApi {\n getState: () => { nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean };\n setState: (partial: Partial<{ nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean }>) => void;\n subscribe: (listener: (state: { nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean }) => void) => () => void;\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n validateConnection: (params: {\n source: string | null;\n target: string | null;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n }) => { valid: boolean; reason?: string };\n selectNodeById: (id: string) => NetworkNode | undefined;\n selectConnectedEdges: (nodeId: string) => NetworkEdge[];\n}\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 store?: NetworkDiagramStoreApi;\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 /** Custom React Flow node types to merge with defaults */\n nodeTypes?: NodeTypes;\n /** Custom React Flow edge types to merge with defaults */\n edgeTypes?: EdgeTypes;\n /** Optional onConnect override (React Flow connection handler) */\n onConnect?: (connection: Connection) => void;\n /** Optional onEdgeUpdate override */\n onEdgeUpdate?: (oldEdge: ReactFlowEdge, newConnection: Connection) => void;\n /** Optional isValidConnection override */\n isValidConnection?: (connection: Connection) => boolean;\n /** Optional connection mode override */\n connectionMode?: ConnectionMode;\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 /** Allow rack-mounted devices to move between racks/ungroup on drag and drop. Defaults to true. */\n reAssignable?: boolean;\n /** Color mode for the diagram */\n colorMode?: 'light' | 'dark' | 'system';\n /** Callback when React Flow instance is initialized */\n onInit?: (instance: ReactFlowInstance) => void;\n /** Callback to get React Flow methods for save/restore */\n onFlowMethods?: (methods: NetworkDiagramFlowMethods) => 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 /** Force read-only behavior for the diagram (no drag/connect/delete/reconnect/pan/zoom edits). */\n readOnly?: boolean;\n /** Centralized interaction options for consistent edit/lock behavior. */\n interaction?: NetworkDiagramInteractionOptions;\n /** Configuration for the floating action panel shown on selected rack/device nodes. */\n actionPanel?: NetworkDiagramActionPanelOptions;\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 /** Optional fitView options passed to React Flow */\n fitViewOptions?: FitViewOptions;\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' | 'AC';\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 AC: {\n type: 'AC',\n color: '#60a5fa', // Blue (generic AC/NEMA)\n borderColor: '#2563eb',\n amperage: 15,\n voltage: 120,\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 const isGenericAc = connector.type === 'AC';\n\n // Size: C13/C14 are intentionally 30% larger while keeping C19/C20 unchanged.\n const width = isHighPower ? 12 : isGenericAc ? 10 : 8 * 1.3;\n const height = isHighPower ? 10 : isGenericAc ? 7 : 5 * 1.3;\n\n // Shape: C13/C14 have chamfered corners, C19/C20 and generic AC use rounded corners.\n const cornerStyle = isHighPower || isGenericAc\n ? { borderRadius: isGenericAc ? '2px' : '3px' }\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' : isGenericAc ? '3.5px' : '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 type { Port } from '../types';\n\nconst DIRECTIONAL_HANDLE_SUFFIX = /-(source|target)$/i;\n\n/**\n * Normalize source/target directional suffixes used for bidirectional handles.\n * Example: `Rear Ports-1-target` -> `Rear Ports-1`.\n */\nexport function normalizeDirectionalHandleId(handleId: string | null | undefined): string {\n if (!handleId) return '';\n return handleId.replace(DIRECTIONAL_HANDLE_SUFFIX, '');\n}\n\n/**\n * Returns true when a port type is considered power-related.\n */\nexport function isPowerPortType(portType: string | undefined): boolean {\n return typeof portType === 'string' && portType.includes('power');\n}\n\n/**\n * Build a stable handle id for a port.\n * Power ports use the label directly to preserve legacy ids.\n */\nexport function buildPortHandleId(\n portBlockName: string,\n port: Pick<Port, 'label' | 'id'> & { type?: string }\n): string {\n if (typeof port.id === 'string' && port.id.length > 0) {\n return port.id;\n }\n return isPowerPortType(port.type) ? port.label : `${portBlockName}-${port.label}`;\n}\n\n/**\n * Heuristic for whether a handle id represents a power endpoint.\n */\nexport function looksLikePowerHandleId(handleId: string): boolean {\n const normalized = normalizeDirectionalHandleId(handleId).toLowerCase();\n return normalized.startsWith('pwr') || normalized.includes('power');\n}\n","import React from 'react';\nimport { Handle, Position, NodeProps, useUpdateNodeInternals } from 'reactflow';\nimport { NetworkNode, Width, PortBlock, Port, PortCableType, DeviceImageFit, PortPosition } from '../types';\nimport { U_HEIGHT_PX, RACK_WIDTH_PX } from '../utils/constants';\nimport { getPowerPortStyle, getDeviceConnectorType } from '../utils/power-connectors';\nimport { getStatusColor } from '../utils/status-colors';\nimport { buildPortHandleId, isPowerPortType } from '../utils/handle-ids';\nimport {\n getRackDeviceBodyWidthPx,\n getRackFaceGapPx,\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\n\ntype DeviceFace = 'front' | 'rear';\ntype HandleRole = 'source' | 'target';\n\ninterface HandlePlacement {\n position: Position;\n style: React.CSSProperties;\n}\n\ntype PortSide = NonNullable<PortPosition['side']>;\n\ntype DeviceNodeCssVars = React.CSSProperties & {\n '--rn-device-bg-image'?: string;\n '--rn-device-bg-position'?: string;\n '--rn-device-bg-repeat'?: string;\n '--rn-device-bg-size'?: string;\n '--rn-device-border-color'?: string;\n '--rn-device-box-shadow'?: string;\n '--rn-device-height'?: string;\n '--rn-device-left'?: string;\n '--rn-device-status-color'?: string;\n '--rn-device-translate-y'?: string;\n '--rn-device-width'?: string;\n};\n\nconst DISCONNECTED_PORT_COLOR = '#6b7280';\nconst DISCONNECTED_PORT_BORDER_COLOR = '#374151';\nconst DEFAULT_CONNECTED_PORT_COLOR = '#10b981';\nconst FILL_BACKGROUND_SIZE = '100% 100%';\n\nconst CONNECTED_CABLE_COLORS: Record<PortCableType, string> = {\n smf: '#fbbf24',\n cat6: '#8b5cf6',\n om3: '#06b6d4',\n om4: '#8b5cf6',\n om5: '#84cc16',\n cat5e: '#3b82f6',\n cat6a: '#ef4444',\n cat7: '#f97316',\n fiber: '#3b82f6',\n ethernet: '#10b981',\n};\n\nconst URL_SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:/;\nconst SAFE_DATA_IMAGE_URL_PATTERN = /^data:image\\//i;\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\nfunction normalizeDeviceType(deviceType: string | undefined): string {\n return (deviceType ?? '').toLowerCase().replace(/_/g, '-');\n}\n\nfunction isRelativeUrl(url: string): boolean {\n return !URL_SCHEME_PATTERN.test(url) && !url.startsWith('//');\n}\n\nfunction sanitizeDeviceImageUrl(url: string | undefined): string | undefined {\n if (!url) return undefined;\n const trimmed = url.trim();\n if (!trimmed) return undefined;\n\n if (isRelativeUrl(trimmed)) {\n return trimmed;\n }\n\n try {\n const parsedUrl = new URL(trimmed);\n const protocol = parsedUrl.protocol.toLowerCase();\n\n if (protocol === 'https:' || protocol === 'blob:') {\n return parsedUrl.href;\n }\n\n if (protocol === 'data:' && SAFE_DATA_IMAGE_URL_PATTERN.test(trimmed)) {\n return trimmed;\n }\n\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction toCssUrlValue(url: string): string {\n return `url(${JSON.stringify(url)})`;\n}\n\nfunction isPowerPort(port: Port): boolean {\n return isPowerPortType(port.type);\n}\n\nfunction getHandleId(portBlockName: string, port: Port): string {\n return buildPortHandleId(portBlockName, port);\n}\n\nfunction hasAbsolutePosition(port: Port): boolean {\n return Boolean(\n port.position &&\n typeof port.position.xPercent === 'number' &&\n typeof port.position.yPercent === 'number'\n );\n}\n\nfunction resolveCurrentFace(\n view: NetworkNode['data']['view'],\n ports: PortBlock[],\n rearPorts: PortBlock[],\n frontImageUrl?: string,\n rearImageUrl?: string\n): DeviceFace {\n const hasFront = ports.length > 0 || !!frontImageUrl;\n const hasRear = rearPorts.length > 0 || !!rearImageUrl;\n return view || (hasFront ? 'front' : hasRear ? 'rear' : 'front');\n}\n\nfunction resolveBackgroundSize(imageFit?: DeviceImageFit, stretchToFit?: boolean): React.CSSProperties['backgroundSize'] {\n if (stretchToFit === true || imageFit === 'fill') {\n return FILL_BACKGROUND_SIZE;\n }\n\n // `none` and `scale-down` are object-fit terms; map them to valid background-size values.\n if (imageFit === 'none') {\n return 'auto';\n }\n if (imageFit === 'scale-down') {\n return 'contain';\n }\n return imageFit ?? 'cover';\n}\n\nfunction getConnectedPortColor(port: Port): string {\n if (isPowerPort(port)) {\n return port.type === 'power_c19' ? '#fbbf24' : '#f59e0b';\n }\n if (port.type === 'console' || port.type === 'mgmt') {\n return '#8b5cf6';\n }\n if (port.type === 'usb') {\n return DEFAULT_CONNECTED_PORT_COLOR;\n }\n if (port.cableType) {\n return CONNECTED_CABLE_COLORS[port.cableType] ?? DEFAULT_CONNECTED_PORT_COLOR;\n }\n return DEFAULT_CONNECTED_PORT_COLOR;\n}\n\nfunction getPortColor(port: Port): string {\n if (!port.connected) {\n return DISCONNECTED_PORT_COLOR;\n }\n return getConnectedPortColor(port);\n}\n\nfunction getPortBlocksSignature(portBlocks: PortBlock[]): string {\n return portBlocks\n .map((block) => {\n const portsSignature = block.ports\n .map((port) => {\n const position = port.position\n ? [\n port.position.side ?? '',\n port.position.offsetPercent ?? '',\n port.position.offsetPx ?? '',\n port.position.xPercent ?? '',\n port.position.yPercent ?? '',\n ].join(':')\n : '';\n return [\n port.id ?? '',\n port.label,\n port.type ?? '',\n port.connected ? '1' : '0',\n port.cableType ?? '',\n port.connectorType ?? '',\n position,\n ].join(':');\n })\n .join(',');\n return `${block.name}[${portsSignature}]`;\n })\n .join('|');\n}\n\nfunction getBaseHandleStyle(\n portWidth: number,\n portHeight: number,\n portColor: string,\n borderColor: string,\n compactMinSize: boolean = false\n): React.CSSProperties {\n return {\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n minWidth: compactMinSize ? `${portWidth}px` : undefined,\n minHeight: compactMinSize ? `${portHeight}px` : undefined,\n background: portColor,\n border: `0.5px solid ${borderColor}`,\n borderRadius: '1px',\n cursor: 'pointer',\n zIndex: 2,\n };\n}\n\nfunction getGenericPortDimensions(faceRegionWidth: number): { width: number; height: number } {\n // Keep non-power connector markers visually consistent across 1U/2U/4U devices.\n // Physical connector size does not scale with chassis height, so size by face width.\n // Increase baseline size so network handles remain visible and usable.\n const width = Math.max(6, Math.min(10, Math.round(faceRegionWidth * 0.025)));\n const height = Math.max(3, Math.min(5, Math.round(width * 0.55)));\n return { width, height };\n}\n\nfunction clampPercent(value: number): number {\n return Math.max(0, Math.min(100, value));\n}\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction mapPortSideToPosition(side: PortSide): Position {\n switch (side) {\n case 'top':\n return Position.Top;\n case 'right':\n return Position.Right;\n case 'bottom':\n return Position.Bottom;\n case 'left':\n return Position.Left;\n default:\n return Position.Top;\n }\n}\n\nfunction inferSideFromAbsolutePercent(xPercent: number, yPercent: number): PortSide {\n const distances: Array<{ side: PortSide; distance: number }> = [\n { side: 'left', distance: xPercent },\n { side: 'right', distance: 100 - xPercent },\n { side: 'top', distance: yPercent },\n { side: 'bottom', distance: 100 - yPercent },\n ];\n distances.sort((a, b) => a.distance - b.distance);\n return distances[0].side;\n}\n\nfunction getCustomHandlePlacement(\n port: Port,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number,\n absoluteCenterYOverridePx?: number\n): HandlePlacement | undefined {\n if (!port.position) {\n return undefined;\n }\n\n const hasAbsoluteCoordinates =\n typeof port.position.xPercent === 'number' && typeof port.position.yPercent === 'number';\n if (hasAbsoluteCoordinates) {\n const xPercent = clampPercent(port.position.xPercent as number);\n const yPercent = clampPercent(port.position.yPercent as number);\n const side = port.position.side ?? inferSideFromAbsolutePercent(xPercent, yPercent);\n const centerX = clampNumber((faceRegionWidth * xPercent) / 100, portWidth / 2, Math.max(portWidth / 2, faceRegionWidth - portWidth / 2));\n const centerY = clampNumber(\n absoluteCenterYOverridePx ?? (deviceHeight * yPercent) / 100,\n portHeight / 2,\n Math.max(portHeight / 2, deviceHeight - portHeight / 2)\n );\n return {\n position: mapPortSideToPosition(side),\n style: {\n left: `${centerX - portWidth / 2}px`,\n top: `${centerY - portHeight / 2}px`,\n right: undefined,\n bottom: undefined,\n transform: 'none',\n },\n };\n }\n\n if (!port.position.side) {\n return undefined;\n }\n\n const side = port.position.side;\n const offsetPercent =\n typeof port.position.offsetPercent === 'number'\n ? clampPercent(port.position.offsetPercent)\n : undefined;\n const offsetPx = typeof port.position.offsetPx === 'number' ? port.position.offsetPx : undefined;\n const minCenterX = portWidth / 2;\n const maxCenterX = Math.max(minCenterX, faceRegionWidth - portWidth / 2);\n const minCenterY = portHeight / 2;\n const maxCenterY = Math.max(minCenterY, deviceHeight - portHeight / 2);\n\n switch (side) {\n case 'top': {\n const rawCenterX = offsetPx !== undefined\n ? offsetPx\n : (faceRegionWidth * (offsetPercent ?? 50)) / 100;\n const centerX = clampNumber(rawCenterX, minCenterX, maxCenterX);\n return {\n position: Position.Top,\n style: {\n top: '0px',\n left: `${centerX}px`,\n right: undefined,\n bottom: undefined,\n transform: 'translate(-50%, 50%)',\n },\n };\n }\n case 'bottom': {\n const rawCenterX = offsetPx !== undefined\n ? offsetPx\n : (faceRegionWidth * (offsetPercent ?? 50)) / 100;\n const centerX = clampNumber(rawCenterX, minCenterX, maxCenterX);\n return {\n position: Position.Bottom,\n style: {\n bottom: '0px',\n left: `${centerX}px`,\n right: undefined,\n top: undefined,\n transform: 'translate(-50%, -50%)',\n },\n };\n }\n case 'left': {\n const rawCenterY = offsetPx !== undefined\n ? offsetPx\n : (deviceHeight * (offsetPercent ?? 50)) / 100;\n const centerY = clampNumber(rawCenterY, minCenterY, maxCenterY);\n return {\n position: Position.Left,\n style: {\n left: '0px',\n top: `${centerY}px`,\n right: undefined,\n bottom: undefined,\n transform: 'translate(50%, -50%)',\n },\n };\n }\n case 'right': {\n const rawCenterY = offsetPx !== undefined\n ? offsetPx\n : (deviceHeight * (offsetPercent ?? 50)) / 100;\n const centerY = clampNumber(rawCenterY, minCenterY, maxCenterY);\n return {\n position: Position.Right,\n style: {\n right: '0px',\n top: `${centerY}px`,\n left: undefined,\n bottom: undefined,\n transform: 'translate(-50%, -50%)',\n },\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction getDistributedRowCenterX(\n rowIndex: number,\n rowCount: number,\n portWidth: number,\n faceRegionWidth: number\n): number {\n const defaultMinCenterX = portWidth / 2;\n const defaultMaxCenterX = Math.max(defaultMinCenterX, faceRegionWidth - (portWidth / 2));\n\n let minCenterX = defaultMinCenterX;\n let maxCenterX = defaultMaxCenterX;\n\n if (rowCount > 1) {\n const availableSpan = defaultMaxCenterX - defaultMinCenterX;\n const naturalStep = availableSpan / (rowCount - 1);\n const maxGapPx = rowCount >= 20 ? 2 : rowCount >= 12 ? 3 : undefined;\n\n if (maxGapPx !== undefined) {\n const compactStep = portWidth + maxGapPx;\n if (naturalStep > compactStep) {\n const compactSpan = compactStep * (rowCount - 1);\n if (compactSpan < availableSpan) {\n const sideInset = (availableSpan - compactSpan) / 2;\n minCenterX = defaultMinCenterX + sideInset;\n maxCenterX = defaultMaxCenterX - sideInset;\n }\n }\n }\n }\n\n return rowCount === 1\n ? (minCenterX + maxCenterX) / 2\n : minCenterX + (rowIndex * (maxCenterX - minCenterX)) / (rowCount - 1);\n}\n\nfunction getAlternatingTopBottomPlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n faceRegionWidth: number\n): HandlePlacement {\n const topRow = portIndex % 2 === 0;\n const topCount = Math.ceil(portCount / 2);\n const bottomCount = Math.floor(portCount / 2);\n const rowCount = Math.max(topRow ? topCount : bottomCount, 1);\n const rowIndex = topRow ? Math.floor(portIndex / 2) : Math.floor((portIndex - 1) / 2);\n const centerX = getDistributedRowCenterX(\n rowIndex,\n rowCount,\n portWidth,\n faceRegionWidth\n );\n\n if (topRow) {\n return {\n position: Position.Top,\n style: {\n transform: 'translateY(50%)',\n left: `${centerX - portWidth / 2}px`,\n },\n };\n }\n\n return {\n position: Position.Bottom,\n style: {\n transform: 'translateY(-50%)',\n left: `${centerX - portWidth / 2}px`,\n },\n };\n}\n\nfunction getAlternatingTopStackPlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number\n): HandlePlacement {\n const topRow = portIndex % 2 === 0;\n const topCount = Math.ceil(portCount / 2);\n const bottomCount = Math.floor(portCount / 2);\n const rowCount = Math.max(topRow ? topCount : bottomCount, 1);\n const rowIndex = topRow ? Math.floor(portIndex / 2) : Math.floor((portIndex - 1) / 2);\n const centerX = getDistributedRowCenterX(\n rowIndex,\n rowCount,\n portWidth,\n faceRegionWidth\n );\n\n const topPaddingPx = 1;\n const rowGapPx = clampNumber(Math.round(portHeight * 0.75), 1, 4);\n const maxTopPx = Math.max(topPaddingPx, deviceHeight - portHeight - 1);\n const secondRowTopPx = clampNumber(topPaddingPx + portHeight + rowGapPx, topPaddingPx, maxTopPx);\n const topPx = topRow ? topPaddingPx : secondRowTopPx;\n\n return {\n position: Position.Top,\n style: {\n transform: 'none',\n left: `${centerX - portWidth / 2}px`,\n top: `${topPx}px`,\n right: undefined,\n bottom: undefined,\n },\n };\n}\n\nfunction getFrontPowerHandlePlacement(\n port: Port,\n portIndex: number,\n portCount: number,\n deviceHeight: number,\n label: string\n): HandlePlacement {\n const connectorType =\n port.connectorType ??\n (port.type === 'power_ac' ? 'AC' : getDeviceConnectorType(label));\n const powerStyle = getPowerPortStyle(connectorType);\n\n let topValue: string;\n if (deviceHeight <= 20) {\n const paddingPx = 2;\n const minTop = paddingPx;\n const maxTop = Math.max(minTop, deviceHeight - powerStyle.height - paddingPx);\n const topPx = portCount <= 1\n ? (minTop + maxTop) / 2\n : minTop + (portIndex * (maxTop - minTop)) / (portCount - 1);\n topValue = `${topPx}px`;\n } else {\n topValue = `${25 + (portIndex * 50)}%`;\n }\n\n return {\n position: Position.Right,\n style: {\n transform: 'translateX(-50%)',\n top: topValue,\n width: `${powerStyle.width}px`,\n height: `${powerStyle.height}px`,\n background: powerStyle.color,\n border: `1px solid ${powerStyle.borderColor}`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: powerStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: powerStyle.borderRadius,\n clipPath: powerStyle.clipPath,\n },\n };\n}\n\nfunction getFrontHandlePlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n faceRegionWidth: number\n): HandlePlacement {\n if (portCount === 1) {\n const rightPadding = Math.max(6, Math.round(faceRegionWidth * 0.04));\n const leftPx = Math.max(portWidth / 2, faceRegionWidth - rightPadding - portWidth / 2);\n return {\n position: Position.Top,\n style: {\n transform: 'translateY(50%)',\n left: `${leftPx}px`,\n right: undefined,\n },\n };\n }\n\n return getAlternatingTopBottomPlacement(portIndex, portCount, portWidth, faceRegionWidth);\n}\n\nfunction getRearHandlePlacement(\n port: Port,\n portIndex: number,\n portCount: number,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number,\n normalizedDeviceType: string,\n label: string\n): HandlePlacement {\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n const isSwitch = normalizedDeviceType === 'switch';\n if (isPatchPanel || isSwitch) {\n return getAlternatingTopBottomPlacement(portIndex, portCount, portWidth, faceRegionWidth);\n }\n\n if (isPowerPort(port)) {\n const connectorType =\n port.connectorType ??\n (port.type === 'power_ac' ? 'AC' : getDeviceConnectorType(label));\n const powerStyle = getPowerPortStyle(connectorType);\n\n let topValue: string;\n if (deviceHeight <= 20) {\n // Keep 1U power handles inside the node even when connectors grow.\n const paddingPx = 2;\n const minTop = paddingPx;\n const maxTop = Math.max(minTop, deviceHeight - powerStyle.height - paddingPx);\n const topPx = portCount <= 1\n ? (minTop + maxTop) / 2\n : minTop + (portIndex * (maxTop - minTop)) / (portCount - 1);\n topValue = `${topPx}px`;\n } else {\n topValue = `${25 + (portIndex * 50)}%`;\n }\n\n return {\n position: Position.Left,\n style: {\n transform: 'translateX(50%)',\n top: topValue,\n width: `${powerStyle.width}px`,\n height: `${powerStyle.height}px`,\n background: powerStyle.color,\n border: `1px solid ${powerStyle.borderColor}`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: powerStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: powerStyle.borderRadius,\n clipPath: powerStyle.clipPath,\n },\n };\n }\n\n return {\n position: Position.Right,\n style: {\n transform: 'translate(-50%, -50%)',\n top: `${\n clampNumber(\n portCount <= 1\n ? deviceHeight / 2\n : (portHeight / 2) + ((portIndex * Math.max(deviceHeight - portHeight, 0)) / Math.max(portCount - 1, 1)),\n portHeight / 2,\n Math.max(portHeight / 2, deviceHeight - portHeight / 2)\n )\n }px`,\n },\n };\n}\n\nfunction getHandleRoles(\n isPower: boolean,\n normalizedDeviceType: string,\n face: DeviceFace,\n isConnected: boolean\n): { primary: HandleRole; secondary?: HandleRole } {\n if (isPower) {\n return { primary: 'target' };\n }\n\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n if (normalizedDeviceType === 'switch' || normalizedDeviceType === 'router') {\n return { primary: 'source', secondary: 'target' };\n }\n if (isPatchPanel) {\n return face === 'rear'\n ? { primary: 'source', secondary: 'target' }\n : { primary: 'target', secondary: 'source' };\n }\n\n return { primary: isConnected ? 'source' : 'target' };\n}\n\n/**\n * Device visualization component with port management.\n * \n * Represents a device that can be placed in a rack. Supports port configuration,\n * U positioning, front/rear views, and various device types (servers, switches, routers, etc.).\n * \n * @example\n * ```tsx\n * {\n * id: 'server-1',\n * type: 'device',\n * position: { x: 120, y: 150 },\n * parentId: 'rack-1',\n * data: {\n * label: 'Web Server',\n * deviceType: 'server',\n * uPosition: 1,\n * ports: [{\n * name: 'Network Ports',\n * ports: [\n * { label: 'eth0', connected: true, type: 'ethernet' }\n * ]\n * }]\n * }\n * }\n * ```\n * \n * @public\n */\nexport const DeviceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ id, data, selected }) => {\n const updateNodeInternals = useUpdateNodeInternals();\n const {\n label,\n status = 'active',\n deviceType = 'server',\n manufacturer,\n uHeight = 1,\n width = Width.FULL,\n ports: rawPorts,\n rearPorts: rawRearPorts,\n view,\n rackWidthPx,\n frontImageUrl,\n rearImageUrl,\n imageFit,\n imagePosition,\n imageRepeat,\n stretchToFit,\n } = data;\n const ports = React.useMemo<PortBlock[]>(\n () => (Array.isArray(rawPorts) ? rawPorts : []),\n [rawPorts]\n );\n const rearPorts = React.useMemo<PortBlock[]>(\n () => (Array.isArray(rawRearPorts) ? rawRearPorts : []),\n [rawRearPorts]\n );\n\n const normalizedDeviceType = normalizeDeviceType(deviceType);\n const effectiveRackWidth = rackWidthPx ?? RACK_WIDTH_PX;\n const splitFaceLayout = isSplitFaceRackLayout(data);\n const mountMode = getRackMountMode(data);\n const resolvedFace = resolveCurrentFace(view, ports, rearPorts, frontImageUrl, rearImageUrl);\n const visibleFaces = React.useMemo(\n () => splitFaceLayout ? getVisibleFacesForMountMode(mountMode) : [resolvedFace],\n [splitFaceLayout, mountMode, resolvedFace]\n );\n const currentFace = visibleFaces[0] ?? resolvedFace;\n const showSplitBothFaces = splitFaceLayout && mountMode === 'both';\n const deviceHeight = uHeight * U_HEIGHT_PX;\n const rackFaceGapPx = getRackFaceGapPx(data);\n const rightFaceOffsetPx = effectiveRackWidth + rackFaceGapPx;\n\n const handleLayoutSignature = React.useMemo(() => {\n return [\n splitFaceLayout ? 'split' : 'single',\n mountMode,\n visibleFaces.join(','),\n currentFace,\n normalizedDeviceType,\n label,\n deviceHeight.toString(),\n effectiveRackWidth.toString(),\n rightFaceOffsetPx.toString(),\n getPortBlocksSignature(ports),\n getPortBlocksSignature(rearPorts),\n ].join('|');\n }, [\n splitFaceLayout,\n mountMode,\n visibleFaces,\n currentFace,\n normalizedDeviceType,\n label,\n deviceHeight,\n effectiveRackWidth,\n rightFaceOffsetPx,\n ports,\n rearPorts,\n ]);\n\n useIsomorphicLayoutEffect(() => {\n updateNodeInternals(id);\n }, [handleLayoutSignature, id, updateNodeInternals]);\n\n const resolveFaceBackgroundStyle = React.useCallback((face: DeviceFace): React.CSSProperties => {\n const backgroundImageUrl = face === 'rear' ? rearImageUrl : frontImageUrl;\n const safeBackgroundImageUrl = sanitizeDeviceImageUrl(backgroundImageUrl);\n if (!safeBackgroundImageUrl) {\n return {};\n }\n\n return {\n backgroundImage: toCssUrlValue(safeBackgroundImageUrl),\n backgroundSize: resolveBackgroundSize(imageFit, stretchToFit),\n backgroundPosition: imagePosition ?? 'center',\n backgroundRepeat: imageRepeat ?? 'no-repeat',\n };\n }, [rearImageUrl, frontImageUrl, imageFit, stretchToFit, imagePosition, imageRepeat]);\n\n const frontBackgroundStyle = React.useMemo(\n () => resolveFaceBackgroundStyle('front'),\n [resolveFaceBackgroundStyle]\n );\n const rearBackgroundStyle = React.useMemo(\n () => resolveFaceBackgroundStyle('rear'),\n [resolveFaceBackgroundStyle]\n );\n const activeBackgroundStyle = currentFace === 'rear' ? rearBackgroundStyle : frontBackgroundStyle;\n\n let rackDeviceWidth: string;\n let rackDeviceLeft: string | undefined;\n if (splitFaceLayout) {\n const bodyWidth = getRackDeviceBodyWidthPx(data, data);\n rackDeviceWidth = `${bodyWidth + 4}px`;\n // In split-face racks, React Flow child node position already carries face offset.\n // Applying an internal left offset here would shift the device twice.\n rackDeviceLeft = undefined;\n } else {\n const fullWidthPx = effectiveRackWidth + 4;\n const halfWidthPx = Math.floor(effectiveRackWidth / 2);\n rackDeviceWidth = width === Width.HALF ? `${halfWidthPx}px` : `${fullWidthPx}px`;\n rackDeviceLeft = width === Width.HALF ? `${halfWidthPx}px` : undefined;\n }\n\n const isOneUServer = normalizedDeviceType === 'server' && uHeight === 1;\n const statusColor = getStatusColor(status);\n const deviceContainerStyle: DeviceNodeCssVars = {\n '--rn-device-bg-image': showSplitBothFaces ? 'none' : String(activeBackgroundStyle.backgroundImage ?? 'none'),\n '--rn-device-bg-position': String(activeBackgroundStyle.backgroundPosition ?? 'center'),\n '--rn-device-bg-repeat': String(activeBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n '--rn-device-bg-size': String(activeBackgroundStyle.backgroundSize ?? 'cover'),\n '--rn-device-border-color': statusColor,\n '--rn-device-box-shadow': selected ? '0 0 0 1px #3b82f6' : '0 1px 2px rgba(0,0,0,0.1)',\n '--rn-device-height': `${deviceHeight}px`,\n '--rn-device-left': rackDeviceLeft ?? 'auto',\n '--rn-device-status-color': statusColor,\n '--rn-device-translate-y': isOneUServer ? '-1px' : '0px',\n '--rn-device-width': rackDeviceWidth,\n };\n\n const frontHandleIds = React.useMemo(() => {\n const ids = new Set<string>();\n for (const block of ports) {\n for (const port of block.ports) {\n ids.add(getHandleId(block.name, port));\n }\n }\n return ids;\n }, [ports]);\n\n const resolveRenderedHandleId = React.useCallback((handleId: string, face: DeviceFace): string => {\n if (face === 'rear' && showSplitBothFaces && frontHandleIds.has(handleId)) {\n return `${handleId}--rear`;\n }\n return handleId;\n }, [frontHandleIds, showSplitBothFaces]);\n\n const computeCompressedTopRowCenterOverrides = React.useCallback((\n portBlockName: string,\n portsInBlock: Port[],\n portHeight: number\n ): Map<string, number> => {\n const overrides = new Map<string, number>();\n if (deviceHeight > 24 || portsInBlock.length <= 1) {\n return overrides;\n }\n\n const absoluteTopPorts = portsInBlock.filter((port) =>\n hasAbsolutePosition(port) && port.position?.side === 'top'\n );\n if (absoluteTopPorts.length <= 1) {\n return overrides;\n }\n\n const uniqueRows = [...new Set(absoluteTopPorts.map((port) => Number(port.position?.yPercent)))]\n .filter((value) => Number.isFinite(value))\n .sort((a, b) => a - b);\n if (uniqueRows.length <= 1) {\n return overrides;\n }\n\n const minCenterY = (portHeight / 2) + 1;\n const maxCenterY = Math.max(minCenterY, deviceHeight - (portHeight / 2) - 1);\n const maxSpread = Math.max(0, maxCenterY - minCenterY);\n const rowCount = uniqueRows.length;\n const preferredGap = Math.max(portHeight + 2, 4);\n const gap = rowCount > 1 ? Math.min(preferredGap, maxSpread / (rowCount - 1)) : 0;\n const spread = gap * Math.max(0, rowCount - 1);\n\n const averageOriginalCenterY =\n absoluteTopPorts.reduce((total, port) => total + ((deviceHeight * Number(port.position?.yPercent)) / 100), 0)\n / absoluteTopPorts.length;\n const startY = clampNumber(\n averageOriginalCenterY - (spread / 2),\n minCenterY,\n maxCenterY - spread\n );\n\n const rowCenterByY = new Map<number, number>();\n uniqueRows.forEach((rowY, index) => {\n rowCenterByY.set(rowY, startY + (index * gap));\n });\n\n for (const port of absoluteTopPorts) {\n const rowY = Number(port.position?.yPercent);\n const centerY = rowCenterByY.get(rowY);\n if (centerY === undefined) {\n continue;\n }\n overrides.set(getHandleId(portBlockName, port), centerY);\n }\n\n return overrides;\n }, [deviceHeight]);\n\n const renderPortsFromArray = React.useCallback((\n portBlocks: PortBlock[],\n face: DeviceFace,\n faceOffsetPx: number = 0,\n faceRegionWidth: number = effectiveRackWidth\n ) => {\n const handles: React.ReactElement[] = [];\n if (portBlocks.length === 0) {\n return handles;\n }\n\n // Keep non-power ports at a stable visual size across chassis heights.\n const { width: portWidth, height: portHeight } = getGenericPortDimensions(faceRegionWidth);\n const totalPortsOnFace = portBlocks.reduce((total, block) => total + block.ports.length, 0);\n const shouldLineUpDenseSwitchPortsAgainstTop =\n (normalizedDeviceType === 'switch' || normalizedDeviceType === 'patch-panel') &&\n totalPortsOnFace >= 24;\n\n for (const portBlock of portBlocks) {\n const compressedTopRowOverrides = computeCompressedTopRowCenterOverrides(\n portBlock.name,\n portBlock.ports,\n portHeight\n );\n for (let portIndex = 0; portIndex < portBlock.ports.length; portIndex += 1) {\n const port = portBlock.ports[portIndex];\n const isPower = isPowerPort(port);\n\n // Resolve actual port dimensions — power ports use connector-specific\n // sizes from getPowerPortStyle which differ from the generic dimensions.\n // Using the correct size here ensures clamp bounds and center-to-corner\n // offsets in getCustomHandlePlacement are accurate.\n let actualPortWidth = portWidth;\n let actualPortHeight = portHeight;\n if (isPower) {\n const connectorType =\n port.connectorType ??\n (port.type === 'power_ac' ? 'AC' : getDeviceConnectorType(label));\n const powerStyle = getPowerPortStyle(connectorType);\n actualPortWidth = powerStyle.width;\n actualPortHeight = powerStyle.height;\n }\n\n const handleId = getHandleId(portBlock.name, port);\n const portColor = getPortColor(port);\n const borderColor = port.connected ? portColor : DISCONNECTED_PORT_BORDER_COLOR;\n const useCompactMinSize = compressedTopRowOverrides.has(handleId);\n const baseStyle = getBaseHandleStyle(\n actualPortWidth,\n actualPortHeight,\n portColor,\n borderColor,\n useCompactMinSize\n );\n const defaultPlacement = face === 'front'\n ? (isPower\n ? getFrontPowerHandlePlacement(port, portIndex, portBlock.ports.length, deviceHeight, label)\n : shouldLineUpDenseSwitchPortsAgainstTop\n ? getAlternatingTopStackPlacement(\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight\n )\n : getFrontHandlePlacement(portIndex, portBlock.ports.length, portWidth, faceRegionWidth))\n : (\n !isPower && shouldLineUpDenseSwitchPortsAgainstTop\n ? getAlternatingTopStackPlacement(\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight\n )\n : getRearHandlePlacement(\n port,\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight,\n normalizedDeviceType,\n label\n )\n );\n const customPlacement = getCustomHandlePlacement(\n port,\n actualPortWidth,\n actualPortHeight,\n faceRegionWidth,\n deviceHeight,\n compressedTopRowOverrides.get(handleId)\n );\n const placement = customPlacement\n ? (isPower\n ? {\n position: customPlacement.position,\n style: {\n ...defaultPlacement.style,\n ...customPlacement.style,\n },\n }\n : customPlacement)\n : defaultPlacement;\n\n const handleStyle = {\n ...baseStyle,\n ...placement.style,\n };\n const translatedHandleStyle: React.CSSProperties = { ...handleStyle };\n if (translatedHandleStyle.left !== undefined && faceOffsetPx !== 0) {\n if (typeof translatedHandleStyle.left === 'number') {\n translatedHandleStyle.left = `${translatedHandleStyle.left + faceOffsetPx}px`;\n } else {\n translatedHandleStyle.left = `calc(${translatedHandleStyle.left} + ${faceOffsetPx}px)`;\n }\n }\n\n if (showSplitBothFaces && translatedHandleStyle.left === undefined) {\n if (placement.position === Position.Left) {\n translatedHandleStyle.left = `${faceOffsetPx}px`;\n translatedHandleStyle.right = undefined;\n } else if (placement.position === Position.Right) {\n translatedHandleStyle.left = `${faceOffsetPx + faceRegionWidth}px`;\n translatedHandleStyle.right = undefined;\n }\n }\n\n const renderedHandleId = resolveRenderedHandleId(handleId, face);\n\n const roles = getHandleRoles(isPower, normalizedDeviceType, face, port.connected);\n if (roles.secondary) {\n const secondaryHandleStyle: React.CSSProperties =\n normalizedDeviceType === 'switch' || normalizedDeviceType === 'router'\n ? {\n ...translatedHandleStyle,\n background: 'transparent',\n border: 'none',\n opacity: 0,\n }\n : translatedHandleStyle;\n const secondaryTitle =\n normalizedDeviceType === 'switch' || normalizedDeviceType === 'router'\n ? `${portBlock.name} - ${port.label} (input) ${port.connected ? '(connected)' : '(disconnected)'}`\n : `${portBlock.name} - ${port.label} (${roles.secondary}) ${port.connected ? '(connected)' : '(disconnected)'}`;\n handles.push(\n <Handle\n key={`${renderedHandleId}-${roles.secondary}`}\n id={`${renderedHandleId}-${roles.secondary}`}\n type={roles.secondary}\n position={placement.position}\n style={secondaryHandleStyle}\n title={secondaryTitle}\n />\n );\n }\n\n handles.push(\n <Handle\n key={renderedHandleId}\n id={renderedHandleId}\n type={roles.primary}\n position={placement.position}\n style={translatedHandleStyle}\n title={`${portBlock.name} - ${port.label} ${port.connected ? '(connected)' : '(disconnected)'}`}\n >\n {isPower ? portIndex + 1 : undefined}\n </Handle>\n );\n }\n }\n\n return handles;\n }, [computeCompressedTopRowCenterOverrides, deviceHeight, effectiveRackWidth, label, normalizedDeviceType, resolveRenderedHandleId, showSplitBothFaces]);\n\n const renderedHandles = React.useMemo(() => {\n const handles: React.ReactElement[] = [];\n for (const face of visibleFaces) {\n if (face === 'front' && ports.length > 0) {\n const faceOffsetPx = showSplitBothFaces ? rightFaceOffsetPx : 0;\n handles.push(...renderPortsFromArray(ports, 'front', faceOffsetPx, effectiveRackWidth));\n }\n if (face === 'rear' && rearPorts.length > 0) {\n const faceOffsetPx = 0;\n handles.push(...renderPortsFromArray(rearPorts, 'rear', faceOffsetPx, effectiveRackWidth));\n }\n }\n return handles;\n }, [visibleFaces, ports, rearPorts, renderPortsFromArray, effectiveRackWidth, showSplitBothFaces, rightFaceOffsetPx]);\n\n return (\n <div\n className={`device-node ${selected ? 'selected' : ''} ${showSplitBothFaces ? 'device-node--split-both' : ''}`}\n style={deviceContainerStyle}\n >\n {showSplitBothFaces && (\n <div\n className=\"device-node__split-face-layer\"\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n pointerEvents: 'none',\n zIndex: 0,\n }}\n >\n <div\n className=\"device-node__split-face device-node__split-face--rear\"\n style={{\n width: `${effectiveRackWidth}px`,\n backgroundImage: String(rearBackgroundStyle.backgroundImage ?? 'none'),\n backgroundPosition: String(rearBackgroundStyle.backgroundPosition ?? 'center'),\n backgroundRepeat: String(rearBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n backgroundSize: String(rearBackgroundStyle.backgroundSize ?? 'cover'),\n }}\n />\n <div\n className=\"device-node__face-bridge\"\n data-testid=\"device-face-bridge\"\n style={{ width: `${rackFaceGapPx}px` }}\n >\n <div className=\"device-node__face-bridge-line\" />\n </div>\n <div\n className=\"device-node__split-face device-node__split-face--front\"\n style={{\n width: `${effectiveRackWidth}px`,\n backgroundImage: String(frontBackgroundStyle.backgroundImage ?? 'none'),\n backgroundPosition: String(frontBackgroundStyle.backgroundPosition ?? 'center'),\n backgroundRepeat: String(frontBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n backgroundSize: String(frontBackgroundStyle.backgroundSize ?? 'cover'),\n }}\n />\n </div>\n )}\n\n <div className=\"device-node__content\" style={{ position: 'relative', zIndex: 1 }}>\n <div className=\"device-node__label\">{label}</div>\n {uHeight > 1 && (\n <div className=\"device-node__manufacturer\">{manufacturer}</div>\n )}\n </div>\n\n {uHeight > 1 && (\n <div className=\"device-node__u-indicator\">{uHeight}U</div>\n )}\n\n <div className=\"device-node__status-indicator\" />\n\n {renderedHandles}\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode, Port, PortBlock, PortPosition } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\nimport { getPowerPortStyle, getPDUPortType } from '../utils/power-connectors';\nimport { buildPortHandleId } from '../utils/handle-ids';\n\nexport enum MgmtUnitPosition {\n TOP = 'top',\n MIDDLE = 'middle',\n BOTTOM = 'bottom'\n}\n\ninterface RenderablePDUPort {\n id: string;\n label: string;\n connectorType: 'C13' | 'C19' | 'AC';\n groupName: string;\n position?: PortPosition;\n}\n\ninterface PortRenderPlacement {\n position: Position;\n leftPx: number;\n topPx: number;\n}\n\nconst PDU_HEADER_HEIGHT = 20;\nconst PDU_BOTTOM_PADDING = 3;\nconst PDU_TOP_PADDING = 2;\nconst GROUP_GAP_UNITS = 1.2;\n\nfunction clampPercent(value: number): number {\n return Math.max(0, Math.min(100, value));\n}\n\nfunction inferClosestSideFromPercent(xPercent: number, yPercent: number): NonNullable<PortPosition['side']> {\n const distances: Array<{ side: NonNullable<PortPosition['side']>; distance: number }> = [\n { side: 'left', distance: xPercent },\n { side: 'right', distance: 100 - xPercent },\n { side: 'top', distance: yPercent },\n { side: 'bottom', distance: 100 - yPercent },\n ];\n distances.sort((a, b) => a.distance - b.distance);\n return distances[0].side;\n}\n\nfunction normalizeConnectorType(value: unknown): 'C13' | 'C19' | 'AC' | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = value.trim().toUpperCase();\n if (normalized === 'C13') return 'C13';\n if (normalized === 'C19') return 'C19';\n if (normalized === 'AC') return 'AC';\n return undefined;\n}\n\nfunction resolvePortConnectorType(\n port: Port,\n fallback: 'C13' | 'C19' | 'AC'\n): 'C13' | 'C19' | 'AC' {\n const fromConnector = normalizeConnectorType(port.connectorType);\n if (fromConnector) {\n return fromConnector;\n }\n\n const type = String(port.type ?? '').toLowerCase();\n if (type.includes('c19')) return 'C19';\n if (type.includes('c13')) return 'C13';\n if (type.includes('power_ac')) return 'AC';\n return fallback;\n}\n\nfunction toPduPortGroups(data: NetworkNode['data']): PortBlock[] {\n if (Array.isArray(data.pduPortGroups) && data.pduPortGroups.length > 0) {\n return data.pduPortGroups;\n }\n if (Array.isArray(data.rearPorts) && data.rearPorts.length > 0) {\n return data.rearPorts;\n }\n if (Array.isArray(data.ports) && data.ports.length > 0) {\n return data.ports;\n }\n return [];\n}\n\nfunction getConnectorSequence(data: NetworkNode['data'], count: number): Array<'C13' | 'C19' | 'AC'> {\n if (!Array.isArray(data.portTypes) || data.portTypes.length === 0) {\n return Array.from({ length: count }, (_, index) => normalizeConnectorType(getPDUPortType(index)) ?? 'C13');\n }\n\n return Array.from({ length: count }, (_, index) => {\n const explicit = normalizeConnectorType(data.portTypes?.[index]);\n if (explicit) {\n return explicit;\n }\n return normalizeConnectorType(getPDUPortType(index)) ?? 'C13';\n });\n}\n\nfunction buildRenderablePorts(data: NetworkNode['data'], powerPorts: number): RenderablePDUPort[] {\n const customGroups = toPduPortGroups(data);\n const connectorSequence = getConnectorSequence(data, powerPorts);\n if (customGroups.length === 0) {\n return Array.from({ length: powerPorts }, (_, index) => ({\n id: `${index + 1}`,\n label: `${index + 1}`,\n connectorType: connectorSequence[index] ?? 'C13',\n groupName: 'Power',\n }));\n }\n\n const ports: RenderablePDUPort[] = [];\n let flatIndex = 0;\n customGroups.forEach((group) => {\n group.ports.forEach((port) => {\n const fallbackType = connectorSequence[flatIndex] ?? 'C13';\n ports.push({\n id: buildPortHandleId(group.name, port),\n label: port.label,\n connectorType: resolvePortConnectorType(port, fallbackType),\n groupName: group.name,\n position: port.position,\n });\n flatIndex += 1;\n });\n });\n return ports;\n}\n\nfunction buildAutoYPositions(ports: RenderablePDUPort[], bodyHeight: number): number[] {\n if (ports.length === 0) {\n return [];\n }\n const drawableHeight = Math.max(bodyHeight - PDU_TOP_PADDING - PDU_BOTTOM_PADDING, 1);\n if (ports.length === 1) {\n return [PDU_HEADER_HEIGHT + PDU_TOP_PADDING + drawableHeight / 2];\n }\n\n const units: number[] = [];\n let cursor = 0;\n for (let index = 0; index < ports.length; index += 1) {\n units.push(cursor);\n cursor += 1;\n if (index < ports.length - 1 && ports[index].groupName !== ports[index + 1].groupName) {\n cursor += GROUP_GAP_UNITS;\n }\n }\n\n const maxUnit = units[units.length - 1] || 1;\n const step = maxUnit > 0 ? drawableHeight / maxUnit : 0;\n return units.map((unit) => PDU_HEADER_HEIGHT + PDU_TOP_PADDING + (unit * step));\n}\n\nfunction resolveCustomPlacement(\n position: PortPosition | undefined,\n fallbackCenterY: number,\n bodyHeight: number,\n widthPx: number,\n handleWidth: number,\n handleHeight: number\n): PortRenderPlacement {\n if (!position) {\n return {\n position: Position.Right,\n leftPx: Math.round((widthPx - handleWidth) / 2) - 1,\n topPx: fallbackCenterY - (handleHeight / 2),\n };\n }\n\n const side = position.side;\n const sourcePosition =\n side === 'left'\n ? Position.Left\n : side === 'top'\n ? Position.Top\n : side === 'bottom'\n ? Position.Bottom\n : Position.Right;\n\n const offsetPercent = typeof position.offsetPercent === 'number' ? clampPercent(position.offsetPercent) : undefined;\n const offsetPx = typeof position.offsetPx === 'number' ? position.offsetPx : undefined;\n const xPercent = typeof position.xPercent === 'number' ? clampPercent(position.xPercent) : undefined;\n const yPercent = typeof position.yPercent === 'number' ? clampPercent(position.yPercent) : undefined;\n\n if (xPercent !== undefined && yPercent !== undefined) {\n const resolvedSide = side ?? inferClosestSideFromPercent(xPercent, yPercent);\n const resolvedPosition =\n resolvedSide === 'left'\n ? Position.Left\n : resolvedSide === 'top'\n ? Position.Top\n : resolvedSide === 'bottom'\n ? Position.Bottom\n : Position.Right;\n const drawableHeight = Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1);\n const centerX = (widthPx * xPercent) / 100;\n const centerY = PDU_HEADER_HEIGHT + (drawableHeight * yPercent) / 100;\n\n return {\n position: resolvedPosition,\n leftPx: centerX - (handleWidth / 2),\n topPx: centerY - (handleHeight / 2),\n };\n }\n\n let centerX = xPercent !== undefined ? (widthPx * xPercent) / 100 : widthPx - (handleWidth / 2) - 1;\n let centerY =\n yPercent !== undefined\n ? PDU_HEADER_HEIGHT + ((Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1) * yPercent) / 100)\n : fallbackCenterY;\n\n if (side === 'top' || side === 'bottom') {\n if (offsetPx !== undefined) {\n centerX = offsetPx;\n } else if (offsetPercent !== undefined) {\n centerX = (widthPx * offsetPercent) / 100;\n }\n centerY = side === 'top'\n ? PDU_HEADER_HEIGHT + (handleHeight / 2)\n : PDU_HEADER_HEIGHT + bodyHeight - (handleHeight / 2);\n } else {\n if (offsetPx !== undefined) {\n centerY = PDU_HEADER_HEIGHT + offsetPx;\n } else if (offsetPercent !== undefined) {\n centerY = PDU_HEADER_HEIGHT + ((Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1) * offsetPercent) / 100);\n }\n if (side === 'left') {\n centerX = handleWidth / 2;\n } else if (side === 'right') {\n centerX = widthPx - (handleWidth / 2) - 1;\n }\n }\n\n return {\n position: sourcePosition,\n leftPx: centerX - (handleWidth / 2),\n topPx: centerY - (handleHeight / 2),\n };\n}\n\nfunction getMgmtPortIndex(mgmtUnit: NetworkNode['data']['mgmt_unit'], totalPorts: number): number {\n if (!mgmtUnit || totalPorts <= 0) {\n return -1;\n }\n if (mgmtUnit === MgmtUnitPosition.TOP) {\n return 0;\n }\n if (mgmtUnit === MgmtUnitPosition.BOTTOM) {\n return totalPorts - 1;\n }\n return Math.floor(totalPorts / 2);\n}\n\nfunction renderMgmtUnit(yCenter: number, widthPx: number): React.ReactElement {\n const mgmtWidth = 16;\n const mgmtHeight = 12;\n return (\n <div\n key=\"mgmt-unit\"\n style={{\n position: 'absolute',\n left: `${(widthPx - mgmtWidth) / 2}px`,\n top: `${yCenter - (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 <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 <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\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,\n widthPx = 15,\n mgmt_unit,\n } = data;\n\n const safePowerPorts = Math.max(0, powerPorts);\n const ports = buildRenderablePorts(data, safePowerPorts);\n const heightPx = heightCm * 4.2;\n const bodyHeight = Math.max(heightPx - PDU_HEADER_HEIGHT, 1);\n const autoYPositions = buildAutoYPositions(ports, bodyHeight);\n const mgmtPortIndex = getMgmtPortIndex(mgmt_unit, ports.length);\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 <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: `${PDU_HEADER_HEIGHT}px`,\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 <div\n style={{\n flex: 1,\n background: 'linear-gradient(180deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n position: 'relative',\n minHeight: `${heightPx - PDU_HEADER_HEIGHT}px`,\n overflow: 'hidden',\n }}\n >\n {ports.map((port, index) => {\n const fallbackCenterY = autoYPositions[index] ?? (PDU_HEADER_HEIGHT + (bodyHeight / 2));\n if (mgmtPortIndex === index) {\n return renderMgmtUnit(fallbackCenterY, widthPx);\n }\n\n const style = getPowerPortStyle(port.connectorType);\n const placement = resolveCustomPlacement(\n port.position,\n fallbackCenterY,\n bodyHeight,\n widthPx,\n style.width,\n style.height\n );\n\n return (\n <Handle\n key={`handle-${port.id}`}\n type=\"source\"\n position={placement.position}\n id={port.id}\n style={{\n position: 'absolute',\n left: `${placement.leftPx}px`,\n top: `${placement.topPx}px`,\n width: `${style.width}px`,\n height: `${style.height}px`,\n background: style.color,\n border: `1px solid ${style.borderColor}`,\n cursor: 'pointer',\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: style.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: style.borderRadius,\n clipPath: style.clipPath,\n }}\n title={`${port.groupName} - ${port.label} (${port.connectorType})`}\n >\n {port.label}\n </Handle>\n );\n })}\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 { getFiberPaint, 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 \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 const connectedIsRibbon =\n !!connectedEdge &&\n (connectedEdge.data?.isRibbon ||\n (connectedEdge.data?.ribbonFiberIds && Array.isArray(connectedEdge.data.ribbonFiberIds)));\n\n const edgeColor = connectedEdge?.data?.color;\n const edgeStriped =\n typeof connectedEdge?.data?.striped === 'boolean' ? connectedEdge.data.striped : undefined;\n\n let fiberPaint = getFiberPaint(fiberIdx);\n if (isRibbonTube || connectedIsRibbon) {\n fiberPaint = getFiberPaint(fiberIdx, { base: '#808080', striped: false });\n } else if (edgeColor || edgeStriped !== undefined) {\n fiberPaint = getFiberPaint(fiberIdx, {\n ...(edgeColor ? { base: edgeColor } : {}),\n ...(edgeStriped !== undefined ? { striped: edgeStriped } : {}),\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': fiberPaint.base,\n backgroundColor: fiberPaint.base,\n };\n \n if (fiberPaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberPaint.backgroundImage;\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={fiberPaint.base}\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={fiberPaint.base}\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","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getFiberPaint, 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 fiberPaint = getFiberPaint(fiberIdx);\n const baseColor = fiberPaint.base;\n\n const left = padding + (i * (handleSize + handleSpacing));\n const top = -(handleSize / 2);\n\n const handleBackground = fiberPaint.backgroundImage ? fiberPaint.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 (fiberPaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberPaint.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","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getFiberPaint, 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 tubePaint = getFiberPaint(tubeIdx);\n const baseColor = tubePaint.base;\n\n const left = padding + (i * (handleWidth + handleSpacing));\n const top = -(handleHeight / 2);\n\n const handleBackground = tubePaint.backgroundImage ? tubePaint.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 (tubePaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = tubePaint.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","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 { HANDLE_EXTENSION_PX } from './constants';\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 * \n * @param node - The coupler node with optional couplerFiberCount in data\n * @returns Object with width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const node = { type: 'coupler', data: { couplerFiberCount: 2 } };\n * const dims = getCouplerDimensions(node);\n * // Returns: { width: 80, height: 30 }\n * ```\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 * \n * @param node - The tube node with optional fibersPerTube in data (default: 12)\n * @returns Object with width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const node = { type: 'tube', data: { fibersPerTube: 12 } };\n * const dims = getTubeDimensions(node);\n * // Returns: { width: calculated, height: 20 }\n * ```\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 * \n * Tray dimensions are fixed and do not depend on node data.\n * \n * @param _node - The tray node (unused, dimensions are fixed)\n * @returns Object with fixed width (TRAY_WIDTH_PX) and height (0)\n * @public\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 the maximum right edge (x + width) of child nodes\n * @param childNodes - Array of child nodes to check\n * @returns Maximum right edge position in pixels\n */\nfunction calculateMaxChildRight(childNodes: NetworkNode[]): number {\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 return maxRight;\n}\n\n/**\n * Calculate the maximum bottom edge (y + height) of child nodes\n * @param childNodes - Array of child nodes to check\n * @param startY - Starting Y position (e.g., header height)\n * @returns Maximum bottom edge position in pixels\n */\nfunction calculateMaxChildBottom(childNodes: NetworkNode[], startY: number = 0): number {\n let maxBottom = startY;\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 return maxBottom;\n}\n\n/**\n * Calculate panel width based on content\n * \n * @param panelNode - The panel node with optional panelWidth in data\n * @returns Panel width in pixels, or default PANEL_WIDTH_PX if not specified\n * @public\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 * \n * @param panelNode - The panel node with optional panelHeight in data\n * @returns Panel height in pixels, or default PANEL_HEIGHT_PX if not specified\n * @public\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 * \n * Calculates the usable width inside a panel after accounting for borders and padding.\n * \n * @param panelNode - The panel node\n * @returns Inner content width in pixels\n * @public\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 * \n * Calculates the X position for the right edge of a coupler within a panel.\n * \n * @param panelNode - The panel node containing the coupler\n * @param couplerWidth - Width of the coupler in pixels\n * @returns X position for the right edge of the coupler\n * @public\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 * \n * Converts a Y pixel coordinate to a slot number (1-indexed).\n * \n * @param y - Y coordinate in pixels\n * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)\n * @returns Slot position (1-indexed)\n * @public\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 * \n * Converts a slot number (1-indexed) to a Y pixel coordinate.\n * \n * @param slot - Slot position (1-indexed)\n * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)\n * @returns Y coordinate in pixels\n * @public\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 * \n * Snaps a coupler's position to the nearest valid slot within a panel.\n * \n * @param coupler - The coupler node to snap\n * @param panel - The panel node containing the coupler\n * @param position - Current position { x, y }\n * @returns Snapped position with optional slotPosition\n * @public\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 * \n * Automatically calculates the width and height of a panel based on its child nodes.\n * Supports special layouts for patch panels with tubes, trays, and couplers.\n * \n * @param panelNode - The panel node\n * @param childNodes - Array of child nodes within the panel\n * @returns Object with calculated width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const panel = { id: 'panel-1', type: 'patch-panel', data: {} };\n * const children = [tubeNode, trayNode, couplerNode];\n * const dims = calculatePanelDimensions(panel, children);\n * ```\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 \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 + HANDLE_EXTENSION_PX;\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 const maxRight = calculateMaxChildRight(childNodes);\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 const maxBottom = calculateMaxChildBottom(childNodes, PANEL_HEADER_HEIGHT);\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 * \n * Calculates the vertical spacing needed between couplers to fit them evenly\n * within the available height.\n * \n * @param numCouplers - Number of couplers to space\n * @param couplerHeight - Height of each coupler in pixels\n * @param availableHeight - Total available height in pixels\n * @returns Spacing between couplers in pixels (includes coupler height)\n * @public\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 * \n * Alias for calculateCouplerSpacing. Calculates spacing between coupler slots.\n * \n * @param numCouplers - Number of couplers to space\n * @param couplerHeight - Height of each coupler in pixels\n * @param availableHeight - Total available height in pixels\n * @returns Spacing between coupler slots in pixels\n * @public\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 * \n * Automatically calculates the width and height of a closure based on its child nodes.\n * Supports special layouts for closures with tubes and trays.\n * Closure layout: [padding] [left tubes] [spacing] [trays] [spacing] [right tubes] [padding]\n * \n * @param closureNode - The closure node\n * @param childNodes - Array of child nodes within the closure\n * @returns Object with calculated width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const closure = { id: 'closure-1', type: 'closure', data: {} };\n * const children = [leftTubeNode, trayNode, rightTubeNode];\n * const dims = calculateClosureDimensions(closure, children);\n * ```\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 \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 + HANDLE_EXTENSION_PX;\n } else {\n // Fallback: calculate based on rightmost child\n const maxRight = calculateMaxChildRight(childNodes);\n width = maxRight + PANEL_PADDING + HANDLE_EXTENSION_PX;\n }\n } else {\n // Standard layout: calculate based on rightmost child\n const maxRight = calculateMaxChildRight(childNodes);\n \n // Add padding and handle extension space\n width = maxRight + PANEL_PADDING + HANDLE_EXTENSION_PX;\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 const maxBottom = calculateMaxChildBottom(childNodes, PANEL_HEADER_HEIGHT);\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';\nimport { normalizeDirectionalHandleId } from './handle-ids';\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 normalizeDirectionalHandleId(handle);\n }\n return normalizeDirectionalHandleId(handle);\n};\n","import type { NetworkNode } from '../types';\nimport {\n buildPortHandleId,\n isPowerPortType,\n looksLikePowerHandleId,\n normalizeDirectionalHandleId,\n} from './handle-ids';\n\nexport type EndpointConnectionKind = 'power' | 'network' | 'unknown';\n\n/**\n * Classify a handle on a node as power, network, or unknown.\n * Used for validation and connection handling.\n */\nexport function getEndpointConnectionKind(\n node?: NetworkNode,\n handle?: string | null\n): EndpointConnectionKind {\n if (!node || !handle) {\n return 'unknown';\n }\n\n const normalizedHandle = normalizeDirectionalHandleId(handle);\n if (!normalizedHandle) {\n return 'unknown';\n }\n\n if (node.type === 'vertical-pdu') {\n return 'power';\n }\n\n const data = node.data ?? {};\n const frontBlocks = Array.isArray(\n (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports\n )\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray(\n (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts\n )\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts!\n : [];\n\n for (const block of [...frontBlocks, ...rearBlocks]) {\n for (const port of block.ports || []) {\n const expectedHandle = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\n if (expectedHandle === normalizedHandle) {\n return isPowerPortType(port.type) ? 'power' : 'network';\n }\n }\n }\n\n if (looksLikePowerHandleId(normalizedHandle) || /^\\d+$/.test(normalizedHandle)) {\n return 'power';\n }\n\n const handleLc = normalizedHandle.toLowerCase();\n const isStandardNetworkHandle =\n handleLc.startsWith('net-') ||\n handleLc.startsWith('port-') ||\n handleLc.startsWith('uplink-') ||\n handleLc.includes('fiber') ||\n handleLc.includes('ports');\n const isCustomPortName =\n /^[A-Z0-9]+-\\d+$/i.test(normalizedHandle) &&\n !handleLc.startsWith('pwr') &&\n !handleLc.startsWith('power');\n\n if (isStandardNetworkHandle || isCustomPortName) {\n return 'network';\n }\n\n return 'unknown';\n}\n\n/**\n * Returns true when the handle on the node is a power endpoint.\n * Used for power connection handling and edge replacement.\n */\nexport function isPowerEndpointHandle(\n node?: NetworkNode,\n handle?: string | null\n): boolean {\n return getEndpointConnectionKind(node, handle) === 'power';\n}\n","import type { NetworkEdge, NetworkNode } from '../types';\nimport { isFiberConnection, normalizeHandle } from '../utils/connection-rules';\nimport { getEndpointConnectionKind } from '../utils/endpoint-kind';\nimport {\n buildPortHandleId,\n isPowerPortType,\n looksLikePowerHandleId,\n normalizeDirectionalHandleId,\n} from '../utils/handle-ids';\nimport {\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\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 /** Optional edge id to ignore during occupancy checks (used for reconnect). */\n ignoreEdgeId?: string;\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 const fiberConnection = isFiberConnection(sourceNode, targetNode);\n\n if (!fiberConnection) {\n const sourceKind = getEndpointConnectionKind(sourceNode, params.sourceHandle);\n const targetKind = getEndpointConnectionKind(targetNode, params.targetHandle);\n\n if (sourceKind !== 'unknown' && targetKind !== 'unknown' && sourceKind !== targetKind) {\n return { valid: false, reason: `Cannot connect ${sourceKind} handle to ${targetKind} handle` };\n }\n\n const isPowerConnection = sourceKind === 'power' && targetKind === 'power';\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n if (isPowerConnection && !hasPduEndpoint) {\n return { valid: false, reason: 'Power connections must include a PDU endpoint' };\n }\n }\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 (params.ignoreEdgeId && e.id === params.ignoreEdgeId) {\n return false;\n }\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 (params.ignoreEdgeId && e.id === params.ignoreEdgeId) {\n return false;\n }\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 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 const rearHandleAliasSuffix = '--rear';\n let normalizedHandleId = normalizeDirectionalHandleId(handleId);\n const hasExplicitRearAlias = normalizedHandleId.endsWith(rearHandleAliasSuffix);\n if (hasExplicitRearAlias) {\n normalizedHandleId = normalizedHandleId.slice(0, -rearHandleAliasSuffix.length);\n }\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 // Split-face rear aliases are explicit and should take precedence over block inference.\n if (hasExplicitRearAlias) {\n return 'rear';\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<{ id?: string; label: string; type?: string }> }> }).ports)\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray((data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts)\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts!\n : [];\n\n // If the handleId matches a power label, treat as rear by default\n if (looksLikePowerHandleId(normalizedHandleId)) 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 expected = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\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 expected = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\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 getNodeParentId = (node: NetworkNode): string | undefined => {\n if (typeof node.parentId === 'string') {\n return node.parentId;\n }\n const legacyParent = (node as NetworkNode & { parentNode?: string }).parentNode;\n if (typeof legacyParent === 'string') {\n return legacyParent;\n }\n return undefined;\n };\n\n const getVisibleFaces = (node: NetworkNode): ViewFace[] => {\n const parentId = getNodeParentId(node);\n const parentRack = parentId ? state.nodes.find((n) => n.id === parentId && n.type === 'rack') : undefined;\n if (parentRack && isSplitFaceRackLayout(parentRack.data)) {\n return getVisibleFacesForMountMode(getRackMountMode(node.data));\n }\n\n const hasRearPorts = Array.isArray(node.data?.rearPorts) && node.data.rearPorts.length > 0;\n const hasFrontPorts = Array.isArray(node.data?.ports) && node.data.ports.length > 0;\n const deviceView: ViewFace = (node.data?.view as ViewFace) || (hasRearPorts && !hasFrontPorts ? 'rear' : 'front');\n return [deviceView];\n };\n\n const resolveEndpointVisibility = (nodeId: string, handle: string | null | undefined): number | undefined => {\n const node = state.nodes.find((n) => n.id === nodeId);\n const isRackDeviceNode =\n !!node &&\n (node.type === 'device' || node.type === 'server' || node.type === 'switch' || node.type === 'router');\n if (!isRackDeviceNode || !node) {\n return undefined;\n }\n\n const normalizedDeviceType = node.data?.deviceType?.toLowerCase().replace(/_/g, '-');\n if (normalizedDeviceType === 'patch-panel') {\n return undefined;\n }\n\n const visibleFaces = getVisibleFaces(node);\n const side = getHandleSide(handle || '', node);\n if (side) {\n return visibleFaces.includes(side) ? 1000 : 500;\n }\n\n const normalizedHandle = (handle || '').toString().replace(/-(source|target)$/i, '');\n const handleLc = normalizedHandle.toLowerCase();\n const isPowerHandle = handleLc.startsWith('pwr') || handleLc.startsWith('power');\n const isStandardNetworkHandle =\n handleLc.startsWith('net-') ||\n handleLc.startsWith('port-') ||\n handleLc.startsWith('uplink-') ||\n handleLc.includes('fiber') ||\n handleLc.includes('ports');\n const isCustomPortName =\n /^[A-Z0-9]+-\\d+$/i.test(normalizedHandle) &&\n !handleLc.startsWith('pwr') &&\n !handleLc.startsWith('power');\n const isNetworkHandle = isStandardNetworkHandle || isCustomPortName;\n\n if (isPowerHandle) {\n return visibleFaces.includes('rear') ? 1000 : 500;\n }\n if (isNetworkHandle) {\n return visibleFaces.includes('front') ? 1000 : 500;\n }\n\n return undefined;\n };\n\n const targetVisibility = resolveEndpointVisibility(edge.target, edge.targetHandle);\n if (targetVisibility !== undefined) {\n return targetVisibility;\n }\n\n const sourceVisibility = resolveEndpointVisibility(edge.source, edge.sourceHandle);\n if (sourceVisibility !== undefined) {\n return sourceVisibility;\n }\n\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","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((_state: NetworkDiagramState) => cb());\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((_state: NetworkDiagramState) => cb());\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((_state: NetworkDiagramState) => cb());\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","import { NetworkNode } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\nimport { getRackTotalWidthPx } from './rack-layout';\n\n/**\n * Calculate the bounding box of a rack node (header + body)\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 // Split-face layout doubles the width and includes the inter-face gap.\n const rackWidth = getRackTotalWidthPx(rack.data);\n const rackHeight = RACK_HEADER_HEIGHT + (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","import { Connection, Edge, addEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\nimport { normalizeDirectionalHandleId } from './handle-ids';\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 /** Which end of the connection to use (source or target) for finding the edge */\n findBy: 'source' | 'target';\n /** Which end of the existing edge to match against. Defaults to findBy. Use 'source' when the connection's target handle is on the edge's source (e.g. replacing switch connection when dragging from server to switch) */\n matchOn?: '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, matchOn = findBy, data } = options;\n\n // Determine which handle to search by from the connection\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 const normalizedHandle = normalizeDirectionalHandleId(handleId);\n\n // Find existing edge - use normalized handle comparison for bidirectional handles (e.g. Network-1-target)\n const existingEdge = edges.find(e => {\n if (matchOn === 'source') {\n return e.source === nodeId && normalizeDirectionalHandleId(e.sourceHandle) === normalizedHandle;\n } else {\n return e.target === nodeId && normalizeDirectionalHandleId(e.targetHandle) === normalizedHandle;\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 type { NetworkNode, RackMountMode } from '../types';\n\ntype MountResolutionNodeData = Pick<\n NetworkNode['data'],\n 'mountMode' | 'ports' | 'rearPorts' | 'frontImageUrl' | 'rearImageUrl' | 'view'\n>;\n\nfunction countPorts(\n portBlocks: MountResolutionNodeData['ports'] | MountResolutionNodeData['rearPorts']\n): number {\n if (!Array.isArray(portBlocks)) {\n return 0;\n }\n\n return portBlocks.reduce((total, block) => {\n return total + (Array.isArray(block.ports) ? block.ports.length : 0);\n }, 0);\n}\n\nfunction hasImage(url: string | undefined): boolean {\n return typeof url === 'string' && url.trim().length > 0;\n}\n\nexport function inferRackMountModeFromFaces(\n nodeData: Pick<MountResolutionNodeData, 'ports' | 'rearPorts' | 'frontImageUrl' | 'rearImageUrl'>\n): RackMountMode | undefined {\n const hasFront = countPorts(nodeData.ports) > 0 || hasImage(nodeData.frontImageUrl);\n const hasRear = countPorts(nodeData.rearPorts) > 0 || hasImage(nodeData.rearImageUrl);\n\n if (hasFront && hasRear) {\n return 'both';\n }\n if (hasFront) {\n return 'front';\n }\n if (hasRear) {\n return 'rear';\n }\n\n return undefined;\n}\n\nexport function resolveSplitRackMountModeForDrop(\n nodeData: MountResolutionNodeData,\n dropRelativeX: number,\n rackWidthPx: number,\n rackFaceGapPx: number\n): RackMountMode {\n const explicitMountMode = nodeData.mountMode;\n if (\n explicitMountMode === 'front' ||\n explicitMountMode === 'rear' ||\n explicitMountMode === 'both'\n ) {\n return explicitMountMode;\n }\n\n const inferredMountMode = inferRackMountModeFromFaces(nodeData);\n if (inferredMountMode) {\n return inferredMountMode;\n }\n\n if (nodeData.view === 'front' || nodeData.view === 'rear') {\n return nodeData.view;\n }\n\n const splitMidpointX = rackWidthPx + rackFaceGapPx / 2;\n return dropRelativeX >= splitMidpointX ? 'front' : 'rear';\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 applyEdgeChanges,\n applyNodeChanges,\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 {\n NetworkDiagramProps,\n NetworkNode,\n NetworkEdge,\n NetworkDiagramFitViewOptions,\n NetworkDiagramToImageOptions,\n NetworkDiagramFlowObject,\n} from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from '../utils/constants';\nimport {\n getReactFlowThemeClassName,\n getReactFlowBackgroundColor,\n getReactFlowWrapperStyle,\n type ColorMode,\n} from '../utils/react-flow-theming';\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 { 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';\nimport { isRackDeviceNode } from '../utils/rack-device-types';\nimport { isPowerEndpointHandle } from '../utils/endpoint-kind';\nimport { normalizeDirectionalHandleId } from '../utils/handle-ids';\nimport {\n getRackFaceGapPx,\n getRackFaceWidthPx,\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\nimport { resolveSplitRackMountModeForDrop } from '../utils/rack-mount-mode';\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 server: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"server\">\n <DeviceNode {...props} />\n </NodeWithDataType>\n ),\n switch: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"switch\">\n <DeviceNode {...props} />\n </NodeWithDataType>\n ),\n router: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"router\">\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\nfunction isSwitchLikeNode(node?: NetworkNode): boolean {\n if (!node) {\n return false;\n }\n\n if (node.type === 'switch') {\n return true;\n }\n\n if (node.type !== 'device') {\n return false;\n }\n\n const deviceType = node.data?.deviceType;\n return typeof deviceType === 'string' && deviceType.toLowerCase().replace(/_/g, '-') === 'switch';\n}\n\n/**\n * In loose mode, dragging from target handles can yield connections where a switch\n * endpoint carries the opposite directional suffix for its side. Canonicalize to:\n * - switch source side => \"<port>\"\n * - switch target side => \"<port>-target\"\n */\nfunction normalizeSwitchPortConnection(\n connection: Connection,\n sourceNode?: NetworkNode,\n targetNode?: NetworkNode\n): Connection {\n let sourceHandle = connection.sourceHandle;\n let targetHandle = connection.targetHandle;\n\n if (isSwitchLikeNode(sourceNode) && sourceHandle && !isPowerEndpointHandle(sourceNode, sourceHandle)) {\n sourceHandle = normalizeDirectionalHandleId(sourceHandle);\n }\n\n if (isSwitchLikeNode(targetNode) && targetHandle && !isPowerEndpointHandle(targetNode, targetHandle)) {\n targetHandle = `${normalizeDirectionalHandleId(targetHandle)}-target`;\n }\n\n if (sourceHandle === connection.sourceHandle && targetHandle === connection.targetHandle) {\n return connection;\n }\n\n return {\n ...connection,\n sourceHandle,\n targetHandle,\n };\n}\n\nconst defaultEdgeTypes: EdgeTypes = {\n fiber: FiberEdge,\n ethernet: FiberEdge,\n power: PowerEdge,\n smoothstep: SmoothStepFiberEdge,\n step: StepFiberEdge,\n 'thick-cable': ThickCableEdge,\n};\n\nconst MAX_TO_IMAGE_WIDTH = 8192;\nconst MAX_TO_IMAGE_HEIGHT = 8192;\nconst MAX_TO_IMAGE_PADDING = 2048;\nconst MAX_TO_IMAGE_PIXEL_RATIO = 4;\n\nfunction clampNumericOption(value: number | undefined, min: number, max: number): number | undefined {\n if (typeof value !== 'number' || Number.isNaN(value)) return undefined;\n return Math.min(max, Math.max(min, value));\n}\n\nfunction normalizeToImageOptions(options?: NetworkDiagramToImageOptions): NetworkDiagramToImageOptions | undefined {\n if (!options) return undefined;\n\n return {\n ...options,\n width: clampNumericOption(options.width, 1, MAX_TO_IMAGE_WIDTH),\n height: clampNumericOption(options.height, 1, MAX_TO_IMAGE_HEIGHT),\n padding: clampNumericOption(options.padding, 0, MAX_TO_IMAGE_PADDING),\n pixelRatio: clampNumericOption(options.pixelRatio, 0.1, MAX_TO_IMAGE_PIXEL_RATIO),\n quality: clampNumericOption(options.quality, 0, 1),\n };\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 nodeTypes: externalNodeTypes,\n edgeTypes: externalEdgeTypes,\n onConnect: externalOnConnect,\n onEdgeUpdate: externalOnEdgeUpdate,\n isValidConnection: externalIsValidConnection,\n connectionMode: externalConnectionMode,\n onViewChange,\n onRackFaceChange,\n className,\n style,\n alignRacksToBottom,\n reAssignable = true,\n colorMode = 'dark',\n onInit,\n onFlowMethods,\n showDownloadButton = false,\n downloadButtonPosition = 'top-right',\n downloadButtonText = 'Download Image',\n downloadButtonStyle,\n useSmoothstepEdgesForTubes = false,\n readOnly = false,\n interaction,\n actionPanel,\n connectOnClick = true,\n panOnDrag = true,\n panOnScroll = true,\n zoomOnScroll = true,\n fitViewOptions,\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] = 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 const isReadOnly = readOnly === true;\n const interactionConfig = useMemo(() => {\n const defaults = {\n // Keep node dragging available on touch devices.\n nodesDraggable: true,\n nodesConnectable: true,\n elementsSelectable: !isMobile,\n edgesFocusable: !isMobile,\n edgesReconnectable: true,\n connectOnClick,\n panOnDrag,\n panOnScroll: panOnScroll && !isMobile,\n zoomOnScroll: zoomOnScroll && !isMobile,\n zoomOnPinch: !isMobile,\n zoomOnDoubleClick: !isMobile,\n allowKeyboardDelete: true,\n showControls: true,\n showMiniMap: !isMobile,\n showInteractiveControl: true,\n };\n\n const merged = { ...defaults, ...(interaction ?? {}) };\n if (!isReadOnly) {\n return merged;\n }\n\n return {\n ...merged,\n nodesDraggable: false,\n nodesConnectable: false,\n elementsSelectable: false,\n edgesFocusable: false,\n edgesReconnectable: false,\n connectOnClick: false,\n panOnDrag: false,\n panOnScroll: false,\n zoomOnScroll: false,\n zoomOnPinch: false,\n zoomOnDoubleClick: false,\n allowKeyboardDelete: false,\n showInteractiveControl: false,\n };\n }, [isMobile, connectOnClick, panOnDrag, panOnScroll, zoomOnScroll, interaction, isReadOnly]);\n\n const actionPanelConfig = useMemo(() => ({\n enabled: actionPanel?.enabled ?? true,\n showRearToggle: actionPanel?.showRearToggle ?? true,\n showDeRack: actionPanel?.showDeRack ?? true,\n }), [actionPanel]);\n \n // Get React Flow methods for save/restore\n const {\n toObject,\n setViewport,\n setNodes: setReactFlowNodes,\n setEdges: setReactFlowEdges,\n getNodes,\n getEdges,\n fitView,\n flowToScreenPosition,\n } = useReactFlow();\n \n // Expose React Flow methods to parent component\n useEffect(() => {\n if (onFlowMethods) {\n onFlowMethods({\n toObject: () => toObject() as NetworkDiagramFlowObject,\n setViewport,\n setNodes: (nodes: NetworkNode[]) => {\n setReactFlowNodes(nodes);\n localStore.setState({ nodes });\n },\n setEdges: (edges: NetworkEdge[]) => {\n setReactFlowEdges(edges);\n localStore.setState({ edges });\n },\n toImage: (options?: NetworkDiagramToImageOptions) => {\n if (!reactFlowWrapper.current) return Promise.reject(new Error('ReactFlow wrapper not available'));\n return toPng(reactFlowWrapper.current, normalizeToImageOptions(options));\n },\n getNodes: () => getNodes() as NetworkNode[],\n getEdges: () => getEdges() as NetworkEdge[],\n fitView: (options?: NetworkDiagramFitViewOptions) => {\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 [isDownloading, setIsDownloading] = useState(false);\n\n const onDownload = useCallback(() => {\n if (isDownloading) {\n return;\n }\n\n if (!reactFlowWrapper.current) {\n if (debug) {\n console.error('ReactFlow wrapper ref is not available');\n }\n return;\n }\n setIsDownloading(true);\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 }).finally(() => {\n setIsDownloading(false);\n });\n }, [colorMode, debug, isDownloading]);\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 {\n ...createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n ),\n ...(externalNodeTypes ?? {}),\n }\n );\n \n // Update nodeTypes ref only when stable callbacks change (they shouldn't, but just in case)\n useEffect(() => {\n nodeTypesRef.current = {\n ...createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n ),\n ...(externalNodeTypes ?? {}),\n };\n }, [onViewChangeStable, onRackFaceChangeStable, getDragOverRackIdStable, externalNodeTypes]);\n \n const mergedEdgeTypes = useMemo(\n () => ({\n ...defaultEdgeTypes,\n ...(externalEdgeTypes ?? {}),\n }),\n [externalEdgeTypes]\n );\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 const getNodeParentId = useCallback((node: Node | null | undefined): string | undefined => {\n if (!node) return undefined;\n if (typeof node.parentId === 'string') {\n return node.parentId;\n }\n const legacyParent = (node as Node & { parentNode?: string }).parentNode;\n if (typeof legacyParent === 'string') {\n return legacyParent;\n }\n return undefined;\n }, []);\n\n const getParentRackNode = useCallback((node: Node | null | undefined): Node | undefined => {\n const parentId = getNodeParentId(node);\n if (!parentId) return undefined;\n const parentNode = getNodeById(parentId);\n if (!parentNode || parentNode.type !== 'rack') {\n return undefined;\n }\n return parentNode;\n }, [getNodeById, getNodeParentId]);\n\n const isSplitFaceRackNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || node.type !== 'rack') {\n return false;\n }\n return isSplitFaceRackLayout((node as NetworkNode).data);\n }, []);\n\n const isSplitFaceRackDeviceNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || !isRackDeviceNode(node as NetworkNode)) {\n return false;\n }\n const parentRack = getParentRackNode(node);\n if (!parentRack) {\n return false;\n }\n return isSplitFaceRackLayout((parentRack as NetworkNode).data);\n }, [getParentRackNode]);\n\n const isPatchPanelDeviceNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || node.type !== 'device') {\n return false;\n }\n\n const deviceType = (node.data as NetworkNode['data'] | undefined)?.deviceType;\n return typeof deviceType === 'string' && deviceType.toLowerCase().replace(/_/g, '-') === 'patch-panel';\n }, []);\n\n const commitNodes = useCallback((nextNodes: Node[]) => {\n latestNodesRef.current = nextNodes;\n const map = new Map<string, Node>();\n nextNodes.forEach((node) => {\n map.set(node.id, node);\n });\n nodesMapRef.current = map;\n setNodes(nextNodes);\n\n if (!isControlled) {\n localStore.setState({ nodes: nextNodes as NetworkNode[] });\n } else {\n externalOnNodesChange?.(nextNodes as NetworkNode[]);\n }\n }, [isControlled, localStore, setNodes, externalOnNodesChange]);\n\n const commitEdges = useCallback((nextEdges: Edge[]) => {\n latestEdgesRef.current = nextEdges;\n setEdges(nextEdges);\n\n if (!isControlled) {\n localStore.setState({ edges: nextEdges as NetworkEdge[] });\n } else {\n externalOnEdgesChange?.(nextEdges as NetworkEdge[]);\n }\n }, [isControlled, localStore, setEdges, externalOnEdgesChange]);\n\n const getAbsoluteNodePosition = useCallback((node: Node): { x: number; y: number } => {\n if (node.positionAbsolute) {\n return node.positionAbsolute;\n }\n\n let x = node.position?.x || 0;\n let y = node.position?.y || 0;\n let parentId = getNodeParentId(node);\n const seenParents = new Set<string>();\n\n while (parentId && !seenParents.has(parentId)) {\n seenParents.add(parentId);\n const parentNode = getNodeById(parentId);\n if (!parentNode) {\n break;\n }\n\n if (parentNode.positionAbsolute) {\n x += parentNode.positionAbsolute.x;\n y += parentNode.positionAbsolute.y;\n break;\n }\n\n x += parentNode.position?.x || 0;\n y += parentNode.position?.y || 0;\n parentId = getNodeParentId(parentNode);\n }\n\n return { x, y };\n }, [getNodeById, getNodeParentId]);\n\n const getRackDropPoint = useCallback((node: Node): { x: number; y: number } => {\n const absolute = getAbsoluteNodePosition(node);\n const width = node.width || 0;\n const height = node.height || 0;\n return {\n x: absolute.x + width / 2,\n y: absolute.y + height / 2,\n };\n }, [getAbsoluteNodePosition]);\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 isRackDeviceNode(node as NetworkNode) &&\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 deviceHeight = node.data.uHeight || 1;\n const calculatedPosition = calculateDevicePositionFromU(\n parentRack as NetworkNode,\n node.data.uPosition,\n deviceHeight,\n node.data\n );\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[]): Node[] | null => {\n if (isReadOnly) {\n return null;\n }\n\n const holderPositionUpdates = new Map<string, number>();\n const uPositionUpdates = new Map<string, number>();\n const parentExtentIds = new Set<string>();\n\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 parentExtentIds.add(node.id);\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 parentExtentIds.add(node.id);\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 holderPositionUpdates.set(node.id, snappedResult.holderPosition);\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n // Handle rack-mounted device positioning within rack\n if (node && isRackDeviceNode(node as NetworkNode) && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack && parentRack.type === 'rack') {\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 uPositionUpdates.set(node.id, snappedResult.uPosition);\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n }\n return change;\n });\n\n const nextNodes = applyNodeChanges(updatedChanges, latestNodesRef.current).map((node) => {\n let updatedNode = node;\n\n if (parentExtentIds.has(node.id)) {\n updatedNode = {\n ...updatedNode,\n extent: 'parent' as const,\n };\n }\n\n const holderPosition = holderPositionUpdates.get(node.id);\n if (holderPosition !== undefined) {\n updatedNode = {\n ...updatedNode,\n data: {\n ...updatedNode.data,\n holderPosition,\n },\n };\n }\n\n const uPosition = uPositionUpdates.get(node.id);\n if (uPosition !== undefined) {\n updatedNode = {\n ...updatedNode,\n data: {\n ...updatedNode.data,\n uPosition,\n },\n };\n }\n\n return updatedNode;\n });\n\n latestNodesRef.current = nextNodes;\n const map = new Map<string, Node>();\n nextNodes.forEach((node) => {\n map.set(node.id, node);\n });\n nodesMapRef.current = map;\n setNodes(nextNodes);\n\n return nextNodes;\n }, [setNodes, getNodeById, isReadOnly]);\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 an ungrouped rack-device is over a rack\n const handleNodeDrag = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n const parentId = getNodeParentId(node);\n if (!reAssignable || !isRackDeviceNode(node as NetworkNode) || parentId) {\n setDragOverRackId(null);\n return;\n }\n\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const dropPoint = getRackDropPoint(node);\n const nearestRack = findNearestRack(dropPoint, racks);\n const nextRackId = nearestRack?.id ?? null;\n\n setDragOverRackId((currentRackId) => (currentRackId === nextRackId ? currentRackId : nextRackId));\n }, [reAssignable, getRackDropPoint, getNodeParentId]);\n\n // Handle drag end to assign ungrouped rack-mounted nodes into racks\n const handleNodeDragStop = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n setDragOverRackId(null);\n\n const parentId = getNodeParentId(node);\n if (!reAssignable || !isRackDeviceNode(node as NetworkNode) || parentId) {\n return;\n }\n\n const absolutePosition = getAbsoluteNodePosition(node);\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const dropPoint = getRackDropPoint(node);\n const nearestRack = findNearestRack(dropPoint, racks);\n const currentNodes = latestNodesRef.current;\n\n if (!nearestRack) {\n // Keep ungrouped as-is when dropped outside any rack.\n return;\n }\n\n const relativeToRack = {\n x: absolutePosition.x - nearestRack.position.x,\n y: absolutePosition.y - nearestRack.position.y,\n };\n\n const baseNode = (currentNodes.find((n) => n.id === node.id) || node) as NetworkNode<'device' | 'server' | 'switch' | 'router'>;\n const splitFaceRack = isSplitFaceRackLayout(nearestRack.data);\n const rackWidthPx = getRackFaceWidthPx(nearestRack.data);\n const rackFaceGapPx = getRackFaceGapPx(nearestRack.data);\n const nextMountMode = splitFaceRack\n ? resolveSplitRackMountModeForDrop(baseNode.data, relativeToRack.x, rackWidthPx, rackFaceGapPx)\n : 'both';\n const initialDeviceX = splitFaceRack && nextMountMode === 'front'\n ? rackWidthPx + rackFaceGapPx\n : 0;\n const nextView =\n nextMountMode === 'rear'\n ? 'rear'\n : nextMountMode === 'front'\n ? 'front'\n : (baseNode.data.view === 'front' || baseNode.data.view === 'rear' ? baseNode.data.view : undefined);\n const candidateNode: NetworkNode<'device' | 'server' | 'switch' | 'router'> = {\n ...baseNode,\n parentId: nearestRack.id,\n extent: 'parent',\n position: { x: initialDeviceX, y: relativeToRack.y },\n data: {\n ...baseNode.data,\n rackLayout: splitFaceRack ? 'split-face' : 'single-face',\n rackWidthPx,\n rackFaceGapPx,\n mountMode: nextMountMode,\n view: nextView,\n },\n };\n\n const nodesForSnapping = currentNodes\n .filter((n) => n.id !== node.id)\n .concat(candidateNode as unknown as Node) as NetworkNode[];\n const snapped = snapToUPosition(\n candidateNode,\n nearestRack,\n candidateNode.position,\n nodesForSnapping\n );\n\n const updatedNodes = currentNodes.map((currentNode) => {\n if (currentNode.id !== node.id) {\n return currentNode;\n }\n\n return {\n ...currentNode,\n parentId: nearestRack.id,\n extent: 'parent',\n position: { x: snapped.x, y: snapped.y },\n data: {\n ...currentNode.data,\n rackLayout: splitFaceRack ? 'split-face' : 'single-face',\n rackWidthPx,\n rackFaceGapPx,\n mountMode: nextMountMode,\n view: nextView,\n uPosition: snapped.uPosition ?? currentNode.data.uPosition,\n },\n } as Node;\n });\n\n commitNodes(updatedNodes);\n }, [reAssignable, getAbsoluteNodePosition, getRackDropPoint, commitNodes, getNodeParentId]);\n\n // Connection validation for React Flow - allows connections before onConnect validation\n const handleIsValidConnection = 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 (!fiberConnection) {\n // For non-fiber connections, final occupancy checks run in onConnect/onEdgeUpdate.\n // This keeps reconnect UX responsive, because isValidConnection does not receive oldEdge context.\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 handleConnect = useCallback(\n (params: Connection) => {\n if (isReadOnly) {\n return;\n }\n\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 normalizedParams = normalizeSwitchPortConnection(\n params,\n sourceNode as NetworkNode | undefined,\n targetNode as NetworkNode | undefined\n );\n\n const initialValidation = localStore.validateConnection({\n source: normalizedParams.source ?? null,\n target: normalizedParams.target ?? null,\n sourceHandle: normalizedParams.sourceHandle,\n targetHandle: normalizedParams.targetHandle,\n });\n if (!initialValidation.valid) {\n const isHandleOccupancyError = (initialValidation.reason ?? '').includes('already connected');\n if (!isHandleOccupancyError) {\n if (debug) {\n console.warn(`Connection rejected: ${initialValidation.reason}`);\n }\n return;\n }\n }\n\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n const sourceIsPowerEndpoint = isPowerEndpointHandle(sourceNode as NetworkNode | undefined, normalizedParams.sourceHandle);\n const targetIsPowerEndpoint = isPowerEndpointHandle(targetNode as NetworkNode | undefined, normalizedParams.targetHandle);\n const isPowerConnection = sourceIsPowerEndpoint && targetIsPowerEndpoint && hasPduEndpoint;\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const isSwitchSource =\n sourceNode?.type === 'switch' ||\n (sourceNode?.type === 'device' && sourceNodeData?.deviceType === 'switch');\n const looksLikePowerTarget = targetIsPowerEndpoint;\n const looksLikeNetworkTarget = !!normalizedParams.targetHandle && (\n normalizedParams.targetHandle.startsWith('net-') || \n normalizedParams.targetHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(normalizeDirectionalHandleId(normalizedParams.targetHandle)) // Custom port names like \"QSFP28-1\", \"Network-1\"\n );\n const looksLikeNetworkSource = !!normalizedParams.sourceHandle && (\n normalizedParams.sourceHandle.startsWith('net-') || \n normalizedParams.sourceHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(normalizeDirectionalHandleId(normalizedParams.sourceHandle))\n );\n const isSwitchTarget = targetNode?.type === 'switch' ||\n (targetNode?.type === 'device' && (targetNode.data as NetworkNode['data'])?.deviceType === 'switch');\n const isPduTarget = targetNode?.type === 'vertical-pdu';\n const looksLikePowerSource = sourceIsPowerEndpoint;\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 = normalizedParams.sourceHandle === 'cable-button' && normalizedParams.targetHandle === 'cable-button';\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable' = 'fiber';\n if (isPowerConnection) {\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(normalizedParams.target!, normalizedParams.targetHandle);\n } else {\n // Cable-to-tube or other: derive from source handle\n colorInfo = deriveFiberColorFromSource(normalizedParams.source!, normalizedParams.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, normalizedParams.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, normalizedParams.targetHandle);\n const sourceHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.source === normalizedParams.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle;\n }\n if (e.target === normalizedParams.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 === normalizedParams.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle;\n }\n if (e.source === normalizedParams.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle;\n }\n return false;\n });\n if (sourceHandleAlreadyConnected || targetHandleAlreadyConnected) {\n const edgesToRemove = new Set<string>();\n for (const edge of latestEdgesRef.current) {\n if (edge.source === normalizedParams.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.sourceHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === normalizedParams.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.targetHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.source === normalizedParams.target) {\n if (normalizeHandle(targetNode as NetworkNode | undefined, edge.sourceHandle) === normalizedTargetHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === normalizedParams.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(normalizedParams, filtered);\n if (edgeFromAddEdge.length === filtered.length) {\n if (debug) {\n console.warn('Handle replacement skipped: addEdge did not create a new edge', normalizedParams);\n }\n } else {\n const newEdge = edgeFromAddEdge[edgeFromAddEdge.length - 1];\n const zIndex = selectEdgeZIndex({ ...normalizedParams, 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 commitEdges([...edgeFromAddEdge.slice(0, -1), edgeWithMetadata]);\n if (debug) {\n console.log('Handle replacement: Replaced', edgesToRemove.size, 'edge(s)');\n }\n return;\n }\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 commitEdges(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 commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'source',\n data: { color: cableColor },\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n // Try replacing as target\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'target',\n data: { color: cableColor },\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Try to replace existing edge on target for PDU power connections (PDU is source of connection)\n if (isPduSource && looksLikePowerTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Try to replace when connecting FROM server TO PDU (PDU is target; server's handle is edge's target)\n if (isPduTarget && looksLikePowerSource && params.source && params.sourceHandle && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'source',\n matchOn: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Allow replacing when connecting FROM device TO switch (Loose mode: user drags from server to switch)\n // The switch's handle is the edge's source, so we match on edge's source\n if (isSwitchTarget && looksLikeNetworkSource && params.source && params.sourceHandle && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n matchOn: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n const validation = localStore.validateConnection({\n source: normalizedParams.source ?? null,\n target: normalizedParams.target ?? null,\n sourceHandle: normalizedParams.sourceHandle,\n targetHandle: normalizedParams.targetHandle,\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: normalizedParams,\n edgeType: looksLikePowerTarget ? 'power' : 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n // Try to replace when connecting from server to PDU (server handle already connected)\n if (isPduTarget && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'source',\n matchOn: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n // Allow replacing when connecting from device to switch (switch is target; edge's switch end is source)\n if (isSwitchTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n matchOn: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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 === normalizedParams.source && e.sourceHandle === normalizedParams.sourceHandle) ||\n (e.target === normalizedParams.source && e.targetHandle === normalizedParams.sourceHandle)\n );\n const targetHandleAlreadyUsed = latestEdgesRef.current.some(\n (e) => (e.target === normalizedParams.target && e.targetHandle === normalizedParams.targetHandle) ||\n (e.source === normalizedParams.target && e.sourceHandle === normalizedParams.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(normalizedParams.sourceHandle || '', sourceNode as NetworkNode | undefined);\n const isTargetSpecialForReplacement = isSpecialHandleForReplacement(normalizedParams.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: normalizedParams.sourceHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.source === normalizedParams.source && e.sourceHandle === normalizedParams.sourceHandle) ||\n (e.target === normalizedParams.source && e.targetHandle === normalizedParams.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: normalizedParams.target,\n targetHandle: normalizedParams.targetHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.target === normalizedParams.target && e.targetHandle === normalizedParams.targetHandle) ||\n (e.source === normalizedParams.target && e.sourceHandle === normalizedParams.targetHandle)\n )\n });\n }\n return;\n }\n\n const edgeToAdd = {\n ...normalizedParams,\n type: edgeType,\n zIndex: selectEdgeZIndex({ ...normalizedParams, id: 'temp-id' } as NetworkEdge),\n data: edgeData,\n } as Connection;\n\n const newEdges = addEdge(edgeToAdd, latestEdgesRef.current);\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 commitEdges(newEdges);\n },\n [commitEdges, localStore, selectEdgeZIndex, getNodeById, debug, deriveFiberColorFromSource, useSmoothstepEdgesForTubes, isReadOnly]\n );\n\n // Handle edge updates (when user drags an edge endpoint to reconnect)\n const handleEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (isReadOnly) {\n return;\n }\n\n if (!newConnection.source || !newConnection.target || !newConnection.sourceHandle || !newConnection.targetHandle) {\n return;\n }\n\n const sourceNode = getNodeById(newConnection.source);\n const targetNode = getNodeById(newConnection.target);\n const normalizedConnection = normalizeSwitchPortConnection(\n newConnection,\n sourceNode as NetworkNode | undefined,\n targetNode as NetworkNode | undefined\n );\n const normalizedSourceHandle = normalizeHandle(sourceNode as NetworkNode | undefined, normalizedConnection.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, normalizedConnection.targetHandle);\n const hasHandleOccupancyConflict = latestEdgesRef.current.some((e) => {\n if (e.id === oldEdge.id) return false;\n const matchesSource =\n (e.source === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle) ||\n (e.target === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle);\n const matchesTarget =\n (e.target === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle) ||\n (e.source === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle);\n return matchesSource || matchesTarget;\n });\n\n const validation = localStore.validateConnection({\n source: normalizedConnection.source ?? null,\n target: normalizedConnection.target ?? null,\n sourceHandle: normalizedConnection.sourceHandle,\n targetHandle: normalizedConnection.targetHandle,\n ignoreEdgeId: oldEdge.id,\n });\n if (!validation.valid) {\n const isHandleOccupancyError = (validation.reason ?? '').includes('already connected');\n if (!(isHandleOccupancyError && hasHandleOccupancyConflict)) {\n if (debug) {\n console.warn(`Edge update rejected: ${validation.reason}`);\n }\n return;\n }\n }\n\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n const sourceIsPowerEndpoint = isPowerEndpointHandle(sourceNode as NetworkNode | undefined, normalizedConnection.sourceHandle);\n const targetIsPowerEndpoint = isPowerEndpointHandle(targetNode as NetworkNode | undefined, normalizedConnection.targetHandle);\n const isPowerConnection = sourceIsPowerEndpoint && targetIsPowerEndpoint && hasPduEndpoint;\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 (isPowerConnection) {\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') {\n const colorInfo = deriveFiberColorFromSource(normalizedConnection.source!, normalizedConnection.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 const existingEdges = latestEdgesRef.current;\n const deduped = existingEdges.filter((e) => {\n if (e.id === oldEdge.id) return true;\n const matchesSource =\n (e.source === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle) ||\n (e.target === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle);\n const matchesTarget =\n (e.target === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle) ||\n (e.source === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle);\n return !(matchesSource || matchesTarget);\n });\n\n const updated = deduped.map((e) => {\n if (e.id === oldEdge.id) {\n return {\n ...e,\n source: normalizedConnection.source!,\n target: normalizedConnection.target!,\n sourceHandle: normalizedConnection.sourceHandle,\n targetHandle: normalizedConnection.targetHandle,\n type: edgeType,\n data: edgeData !== undefined ? { ...e.data, ...edgeData } : e.data,\n zIndex: selectEdgeZIndex({ ...normalizedConnection, id: e.id, type: edgeType } as NetworkEdge),\n style: { ...e.style, zIndex: selectEdgeZIndex({ ...normalizedConnection, id: e.id, type: edgeType } as NetworkEdge) },\n };\n }\n return e;\n });\n commitEdges(updated);\n },\n [commitEdges, getNodeById, deriveFiberColorFromSource, selectEdgeZIndex, useSmoothstepEdgesForTubes, debug, localStore, isReadOnly]\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 const allNodes = getNodes();\n let selectedTarget = node;\n\n // If a tube is clicked and it has a parent cable, select the parent instead\n const parentId = getNodeParentId(node);\n if (node.type === 'tube' && parentId && !isCommandClick) {\n const parentNode = allNodes.find(n => n.id === parentId && (n.type === 'cable' || n.type === 'multi-tube-cable'));\n if (parentNode) {\n selectedTarget = parentNode;\n }\n }\n\n // Mirror selected node locally so action buttons do not depend on RF selection subscriptions.\n setSelectedNode(selectedTarget);\n setSelectedEdges([]);\n setNodes((nds) =>\n nds.map((n) => {\n const shouldSelect = n.id === selectedTarget.id;\n return n.selected === shouldSelect ? n : { ...n, selected: shouldSelect };\n })\n );\n\n if (isCommandClick && isRackDeviceNode(selectedTarget as NetworkNode) && !isSplitFaceRackDeviceNode(selectedTarget)) {\n const data = selectedTarget.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 ${selectedTarget.id} from ${currentView} to ${nextView}`);\n }\n\n // Use external onViewChange instead of internal state management\n if (onViewChange) {\n onViewChange(selectedTarget.id, nextView);\n }\n }\n\n onNodeClick && onNodeClick(selectedTarget as NetworkNode);\n },\n [onViewChange, onNodeClick, debug, getNodes, setNodes, isMobile, getNodeParentId, isSplitFaceRackDeviceNode]\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 setSelectedNode(null);\n setSelectedEdges([edge]);\n setNodes((nds) => nds.map((n) => (n.selected ? { ...n, selected: false } : n)));\n onNodeClick?.(null);\n if (onEdgeClick) {\n onEdgeClick(edge as NetworkEdge);\n }\n },\n [onEdgeClick, onNodeClick, setNodes]\n );\n\n const handlePaneClick = useCallback(() => {\n setSelectedNode(null);\n setSelectedEdges([]);\n setNodes((nds) => nds.map((n) => (n.selected ? { ...n, selected: false } : n)));\n onNodeClick?.(null);\n }, [onNodeClick, setNodes]);\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: ({ edges }) => {\n // Track selected edges for deletion\n setSelectedEdges(edges || []);\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 if (!interactionConfig.allowKeyboardDelete) {\n return;\n }\n\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 const remainingEdges = latestEdgesRef.current.filter(e => !edgeIdsToDelete.has(e.id));\n commitEdges(remainingEdges);\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, commitEdges, debug, interactionConfig.allowKeyboardDelete]);\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 (isReadOnly) return;\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 if (isSplitFaceRackLayout(nodeData)) {\n return;\n }\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 (isRackDeviceNode(node as NetworkNode)) {\n if (isSplitFaceRackDeviceNode(node)) {\n return;\n }\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, isReadOnly, isSplitFaceRackDeviceNode]);\n\n const deRackSelectedDevice = useCallback(() => {\n if (isReadOnly || !reAssignable || !selectedNode) return;\n if (!isRackDeviceNode(selectedNode)) return;\n\n const node = getNodeById(selectedNode.id);\n const parentId = getNodeParentId(node);\n if (!node || !isRackDeviceNode(node as NetworkNode) || !parentId) return;\n\n const absolutePosition = getAbsoluteNodePosition(node);\n const currentNodes = latestNodesRef.current;\n const updatedNodes = currentNodes.map((currentNode) => {\n if (currentNode.id !== node.id) {\n return currentNode;\n }\n\n return {\n ...currentNode,\n parentId: undefined,\n parentNode: undefined,\n extent: undefined,\n position: absolutePosition,\n data: {\n ...currentNode.data,\n uPosition: undefined,\n },\n } as Node;\n });\n\n commitNodes(updatedNodes);\n }, [isReadOnly, reAssignable, selectedNode, getNodeById, getAbsoluteNodePosition, commitNodes, getNodeParentId]);\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\n const resolveVisibleFaces = (node: Node | undefined): Array<'front' | 'rear'> | undefined => {\n if (!node || !isRackDeviceNode(node as NetworkNode)) {\n return undefined;\n }\n const nodeData = (node as NetworkNode).data ?? {};\n const parentId =\n typeof node.parentId === 'string'\n ? node.parentId\n : (node as Node & { parentNode?: string }).parentNode;\n const parentRack = parentId ? nodesMap.get(parentId) : undefined;\n if (parentRack && parentRack.type === 'rack' && isSplitFaceRackLayout((parentRack as NetworkNode).data)) {\n return getVisibleFacesForMountMode(getRackMountMode(nodeData));\n }\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' | undefined) || (hasRear && !hasFront ? 'rear' : 'front');\n return [view];\n };\n\n // Determine endpoint views\n const sourceVisibleFaces = resolveVisibleFaces(sourceNode);\n const targetVisibleFaces = resolveVisibleFaces(targetNode);\n const sourceIsPatchPanel = isPatchPanelDeviceNode(sourceNode);\n const targetIsPatchPanel = isPatchPanelDeviceNode(targetNode);\n const sourceHasMismatchedSide =\n isRackDeviceNode(sourceNode as NetworkNode | undefined) &&\n !sourceIsPatchPanel &&\n !!sourceVisibleFaces &&\n !!sourceSide &&\n !sourceVisibleFaces.includes(sourceSide);\n const targetHasMismatchedSide =\n isRackDeviceNode(targetNode as NetworkNode | undefined) &&\n !targetIsPatchPanel &&\n !!targetVisibleFaces &&\n !!targetSide &&\n !targetVisibleFaces.includes(targetSide);\n // Hide edges when either endpoint handle belongs to the opposite face.\n const hideForSource = sourceHasMismatchedSide;\n const hideForTarget = targetHasMismatchedSide;\n const shouldHide = hideForSource || hideForTarget;\n // Compose styles\n let nextStyle: React.CSSProperties | undefined = edge.style;\n if (shouldHide) {\n nextStyle = { ...edge.style, opacity: 0, pointerEvents: 'none' as const, zIndex: 0 };\n } else if (edge.style) {\n const isHiddenStyle =\n edge.style.opacity === 0 &&\n edge.style.pointerEvents === 'none' &&\n edge.style.zIndex === 0;\n if (isHiddenStyle) {\n const rest = { ...edge.style };\n delete rest.opacity;\n delete rest.pointerEvents;\n delete rest.zIndex;\n nextStyle = Object.keys(rest).length > 0 ? rest : undefined;\n }\n }\n return {\n ...edge,\n style: nextStyle,\n className: animatingEdges.has(edge.id) ? 'edge-connecting' : edge.className,\n };\n });\n }, [reactFlowEdges, animatingEdges, isPatchPanelDeviceNode]);\n\n const selectedNodeForActions = useMemo<Node | null>(() => {\n if (!selectedNode) {\n return null;\n }\n return getNodeById(selectedNode.id) ?? selectedNode;\n }, [selectedNode, getNodeById]);\n\n const selectedActionButtons = useMemo(() => {\n if (!selectedNodeForActions || !actionPanelConfig.enabled || isReadOnly) {\n return {\n showRearToggle: false,\n showDeRack: false,\n count: 0,\n };\n }\n\n const supportsRearToggle = (() => {\n if (selectedNodeForActions.type === 'rack') {\n return !isSplitFaceRackNode(selectedNodeForActions);\n }\n if (isRackDeviceNode(selectedNodeForActions)) {\n return !isSplitFaceRackDeviceNode(selectedNodeForActions);\n }\n return false;\n })();\n const showRearToggle = actionPanelConfig.showRearToggle && supportsRearToggle;\n const showDeRack =\n actionPanelConfig.showDeRack &&\n reAssignable &&\n !isReadOnly &&\n isRackDeviceNode(selectedNodeForActions) &&\n !!getNodeParentId(selectedNodeForActions);\n\n return {\n showRearToggle,\n showDeRack,\n count: (showRearToggle ? 1 : 0) + (showDeRack ? 1 : 0),\n };\n }, [selectedNodeForActions, actionPanelConfig, reAssignable, isReadOnly, getNodeParentId, isSplitFaceRackDeviceNode, isSplitFaceRackNode]);\n\n const actionPanelPosition = useMemo<{ left: number; top: number } | null>(() => {\n if (!selectedNodeForActions || selectedActionButtons.count === 0 || !reactFlowWrapper.current) {\n return null;\n }\n\n const wrapperRect = reactFlowWrapper.current.getBoundingClientRect();\n if (wrapperRect.width <= 0 || wrapperRect.height <= 0) {\n return null;\n }\n\n const absolute = selectedNodeForActions.positionAbsolute ?? getAbsoluteNodePosition(selectedNodeForActions);\n const nodeWidth = selectedNodeForActions.width || 0;\n const nodeHeight = selectedNodeForActions.height || 0;\n const panelWidth = selectedActionButtons.count > 1 ? 220 : 110;\n const panelHeight = 34;\n\n try {\n const topCenterAnchor = flowToScreenPosition({\n x: absolute.x + nodeWidth / 2,\n y: absolute.y,\n });\n const bottomCenterAnchor = flowToScreenPosition({\n x: absolute.x + nodeWidth / 2,\n y: absolute.y + nodeHeight,\n });\n\n let left = topCenterAnchor.x - wrapperRect.left - panelWidth / 2;\n let top = topCenterAnchor.y - wrapperRect.top - panelHeight - 10;\n\n // If there isn't enough space above, place below the node.\n if (top < 8) {\n top = bottomCenterAnchor.y - wrapperRect.top + 10;\n }\n\n left = Math.max(8, Math.min(left, wrapperRect.width - panelWidth - 8));\n top = Math.max(8, Math.min(top, wrapperRect.height - panelHeight - 8));\n\n return { left, top };\n } catch {\n return null;\n }\n }, [\n selectedNodeForActions,\n selectedActionButtons,\n getAbsoluteNodePosition,\n flowToScreenPosition,\n ]);\n\n const flowClassName = getReactFlowThemeClassName(colorMode as ColorMode, className);\n const wrapperStyle = getReactFlowWrapperStyle(colorMode as ColorMode, {\n touchAction: 'none', // Prevent default touch behaviors like scrolling\n ...style,\n });\n const connectHandler = externalOnConnect ?? handleConnect;\n const edgeUpdateHandler = externalOnEdgeUpdate ?? handleEdgeUpdate;\n const connectionValidator = externalIsValidConnection ?? handleIsValidConnection;\n\n return (\n <div \n ref={reactFlowWrapper} \n className={flowClassName}\n style={wrapperStyle}\n >\n <ReactFlow\n nodes={reactFlowNodes}\n edges={edgesWithAnimation}\n onNodesChange={(changes) => {\n if (isReadOnly) {\n return;\n }\n const nextNodes = handleNodesChange(changes);\n if (!nextNodes) {\n return;\n }\n if (!isControlled) {\n localStore.setState({ nodes: nextNodes as NetworkNode[] });\n } else {\n externalOnNodesChange && externalOnNodesChange(nextNodes as NetworkNode[]);\n }\n }}\n onEdgesChange={(changes) => {\n if (isReadOnly) {\n return;\n }\n\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 const nextEdges = applyEdgeChanges(filteredChanges, latestEdgesRef.current);\n onEdgesChange(filteredChanges);\n if (!isControlled) {\n localStore.setState({ edges: nextEdges as NetworkEdge[] });\n } else {\n externalOnEdgesChange && externalOnEdgesChange(nextEdges as NetworkEdge[]);\n }\n }\n }}\n onConnect={isReadOnly ? undefined : connectHandler}\n onConnectStart={handleConnectStart}\n onConnectEnd={handleConnectEnd}\n onEdgeUpdate={isReadOnly ? undefined : edgeUpdateHandler}\n isValidConnection={connectionValidator}\n connectionMode={externalConnectionMode}\n onNodeClick={handleNodeClick}\n onNodeDoubleClick={handleNodeDoubleClick}\n onPaneClick={handlePaneClick}\n onNodeDragStart={handleNodeDragStart}\n onNodeDrag={handleNodeDrag}\n onNodeDragStop={handleNodeDragStop}\n onEdgeClick={handleEdgeClick}\n onInit={onInit}\n nodeTypes={nodeTypesRef.current}\n edgeTypes={mergedEdgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: interactionConfig.edgesReconnectable\n }}\n nodesDraggable={interactionConfig.nodesDraggable}\n nodesConnectable={interactionConfig.nodesConnectable}\n elementsSelectable={interactionConfig.elementsSelectable}\n edgesFocusable={interactionConfig.edgesFocusable}\n elevateNodesOnSelect={false}\n selectNodesOnDrag={false}\n connectOnClick={interactionConfig.connectOnClick}\n panOnDrag={interactionConfig.panOnDrag}\n panOnScroll={interactionConfig.panOnScroll}\n zoomOnScroll={interactionConfig.zoomOnScroll}\n zoomOnPinch={interactionConfig.zoomOnPinch}\n zoomOnDoubleClick={interactionConfig.zoomOnDoubleClick}\n preventScrolling={isMobile}\n onlyRenderVisibleElements={true}\n fitView\n fitViewOptions={fitViewOptions}\n proOptions={{ hideAttribution: true }}\n >\n <Background color={getReactFlowBackgroundColor(colorMode as ColorMode)} />\n {interactionConfig.showControls && (\n <Controls showInteractive={interactionConfig.showInteractiveControl} />\n )}\n {interactionConfig.showMiniMap && <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 disabled={isDownloading}\n aria-busy={isDownloading}\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: isDownloading ? 'not-allowed' : 'pointer',\n opacity: isDownloading ? 0.7 : 1,\n transition: 'all 0.2s ease',\n ...downloadButtonStyle,\n }}\n >\n {isDownloading ? `${downloadButtonText}...` : downloadButtonText}\n </button>\n )}\n {selectedNodeForActions &&\n actionPanelPosition &&\n selectedActionButtons.count > 0 && (\n <div\n style={{\n position: 'absolute',\n top: actionPanelPosition.top,\n left: actionPanelPosition.left,\n display: 'flex',\n gap: 8,\n zIndex: 2000,\n }}\n >\n {selectedActionButtons.showRearToggle && (\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 = selectedNodeForActions.data as NetworkNode['data'];\n if (selectedNodeForActions.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 = selectedNodeForActions.data as NetworkNode['data'];\n if (selectedNodeForActions.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 )}\n {selectedActionButtons.showDeRack && (\n <button\n onClick={(e) => { e.preventDefault(); deRackSelectedDevice(); }}\n style={{\n background: '#7f1d1d',\n color: '#fee2e2',\n border: '1px solid #b91c1c',\n borderRadius: 4,\n padding: '6px 10px',\n fontSize: 11,\n fontFamily: 'monospace',\n cursor: 'pointer',\n }}\n title=\"Remove device from rack so it can be moved/reassigned\"\n >\n De-rack\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Main component for rendering interactive network diagrams.\n * \n * The NetworkDiagram component provides a complete solution for visualizing\n * network infrastructure including racks, devices, fiber connections, and power distribution.\n * \n * @example\n * ```tsx\n * import { NetworkDiagram, NetworkNode, NetworkEdge } from '@mp70/react-networks';\n * \n * const nodes: NetworkNode[] = [\n * {\n * id: 'rack-1',\n * type: 'rack',\n * position: { x: 100, y: 100 },\n * data: { label: 'Main Rack', uHeight: 42 }\n * }\n * ];\n * \n * <NetworkDiagram nodes={nodes} edges={[]} />\n * ```\n * \n * @public\n */\nexport const NetworkDiagram: React.FC<NetworkDiagramProps> = (props) => {\n return (\n <ReactFlowProvider>\n <NetworkDiagramInner {...props} />\n </ReactFlowProvider>\n );\n};\n","import React, { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface DiagramErrorBoundaryProps {\n /** Content to render when an error is caught */\n children: ReactNode;\n /** Optional fallback UI when an error occurs (default: simple message) */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught (e.g. for logging) */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Error boundary that catches errors in the diagram tree (e.g. React Flow,\n * custom nodes) and renders a fallback instead of crashing the whole app.\n * Wrap &lt;NetworkDiagram&gt; (or the diagram subtree) with this for production.\n *\n * @example\n * ```tsx\n * <DiagramErrorBoundary\n * fallback={(error, reset) => (\n * <div>\n * <p>Diagram failed: {error.message}</p>\n * <button onClick={reset}>Try again</button>\n * </div>\n * )}\n * onError={(err, info) => logToService(err, info)}\n * >\n * <NetworkDiagram nodes={nodes} edges={edges} />\n * </DiagramErrorBoundary>\n * ```\n */\nexport class DiagramErrorBoundary extends Component<DiagramErrorBoundaryProps, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ error: null });\n };\n\n render(): ReactNode {\n const { error } = this.state;\n const { children, fallback } = this.props;\n\n if (error) {\n if (typeof fallback === 'function') {\n return fallback(error, this.reset);\n }\n if (fallback != null) {\n return fallback;\n }\n return (\n <div\n role=\"alert\"\n style={{\n padding: 16,\n margin: 8,\n border: '1px solid #e53e3e',\n borderRadius: 4,\n backgroundColor: '#fff5f5',\n color: '#c53030',\n }}\n >\n <strong>Diagram error</strong>: {error.message}\n <button\n type=\"button\"\n onClick={this.reset}\n style={{ marginLeft: 12, padding: '4px 8px', cursor: 'pointer' }}\n >\n Try again\n </button>\n </div>\n );\n }\n\n return children;\n }\n}\n","import { baseColorFor, fiberSolidOrStriped, getFiberColor, isStriped } from './fiber-colors';\nimport type { FibreFlowCable } from '../types/fibre-flow';\n\nexport interface FibreFlowRow {\n key: string;\n tubeIndex?: number;\n fiberIndex: number;\n y: number;\n color: string;\n striped: boolean;\n backgroundImage?: string;\n}\n\nexport interface FibreFlowTubeLabel {\n tubeIndex: number;\n y: number;\n label: string;\n color: string;\n}\n\nexport interface FibreFlowCableLayout {\n rows: FibreFlowRow[];\n tubeLabels: FibreFlowTubeLabel[];\n height: number;\n}\n\ninterface LayoutOptions {\n rowHeight: number;\n tubeGap: number;\n}\n\nexport function buildFibreFlowCableLayout(\n cable: FibreFlowCable,\n { rowHeight, tubeGap }: LayoutOptions\n): FibreFlowCableLayout {\n const rows: FibreFlowRow[] = [];\n const tubeLabels: FibreFlowTubeLabel[] = [];\n\n const kind = cable.kind ?? (cable.tubeCount ? 'tube' : 'simple');\n const tubeCount = kind === 'tube' ? Math.max(1, Math.min(24, cable.tubeCount ?? 1)) : 1;\n const fibersPerTube =\n kind === 'tube'\n ? Math.max(1, Math.min(24, cable.fibersPerTube ?? 12))\n : Math.max(1, Math.min(24, cable.fiberCount ?? 12));\n const tubeStartIndex = Math.max(1, cable.tubeStartIndex ?? 1);\n const fiberStartIndex = Math.max(1, cable.fiberStartIndex ?? 1);\n\n let currentY = 0;\n\n for (let tubeOffset = 0; tubeOffset < tubeCount; tubeOffset += 1) {\n const tubeIndex = tubeStartIndex + tubeOffset;\n const tubeColor = cable.tubeColorMap?.[tubeIndex];\n tubeLabels.push({\n tubeIndex,\n y: currentY,\n label: `T${tubeIndex}`,\n color: tubeColor ?? baseColorFor(tubeIndex),\n });\n\n for (let fiberOffset = 0; fiberOffset < fibersPerTube; fiberOffset += 1) {\n const fiberIndex = fiberStartIndex + fiberOffset;\n const style = fiberSolidOrStriped(fiberIndex);\n rows.push({\n key: `${tubeIndex}-${fiberIndex}`,\n tubeIndex: kind === 'tube' ? tubeIndex : undefined,\n fiberIndex,\n y: currentY,\n color: getFiberColor(fiberIndex),\n striped: isStriped(fiberIndex),\n backgroundImage: typeof style.backgroundImage === 'string' ? style.backgroundImage : undefined,\n });\n currentY += rowHeight;\n }\n\n if (tubeOffset < tubeCount - 1) {\n currentY += tubeGap;\n }\n }\n\n return {\n rows,\n tubeLabels,\n height: currentY,\n };\n}\n","import React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n addEdge,\n BaseEdge,\n Connection,\n ConnectionMode,\n Edge,\n EdgeLabelRenderer,\n EdgeProps,\n Handle,\n NodeProps,\n Position,\n getBezierPath,\n} from 'reactflow';\nimport { NetworkDiagram } from './NetworkDiagram';\nimport type {\n FibreFlowCableNodeData as BaseFibreFlowCableNodeData,\n FibreFlowClosureNodeData,\n NetworkEdge,\n NetworkNode,\n} from '../types';\nimport type { FibreFlowCircuit, FibreFlowClosure, FibreFlowEndpoint } from '../types/fibre-flow';\nimport { buildFibreFlowCableLayout, FibreFlowCableLayout } from '../utils/fibre-flow-layout';\nimport { getFiberColor, isStriped } from '../utils/fiber-colors';\n\ntype FibreFlowLayoutDirection = 'horizontal' | 'vertical';\ntype FibreFlowColorMode = 'dark' | 'light';\n\ntype FibreFlowCableNodeData = Omit<BaseFibreFlowCableNodeData, 'layout'> & {\n layout: FibreFlowCableLayout;\n};\n\ninterface FibreFlowEdgeData {\n label?: string;\n lossDb?: number;\n color?: string;\n sourceColor?: string; // Color from source fiber handle\n targetColor?: string; // Color from target fiber handle\n sourceStriped?: boolean;\n targetStriped?: boolean;\n highlighted?: boolean;\n dimmed?: boolean;\n circuitId?: string;\n circuitLabel?: string;\n showCircuitId?: boolean;\n}\n\ninterface FibreFlowLinkEdgeData {\n label?: string;\n color?: string;\n}\n\ntype FibreFlowMapNode =\n | NetworkNode<'fibre-flow-cable', FibreFlowCableNodeData>\n | NetworkNode<'fibre-flow-closure', FibreFlowClosureNodeData>;\ntype FibreFlowMapEdgeType = 'fibre-flow' | 'fibre-flow-link';\ntype FibreFlowMapEdge = Omit<NetworkEdge<FibreFlowEdgeData | FibreFlowLinkEdgeData>, 'type'> & {\n type: FibreFlowMapEdgeType;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null;\n};\n\nconst isFibreFlowNode = (node: NetworkNode): node is FibreFlowMapNode => {\n if (!isRecord(node.data)) {\n return false;\n }\n\n if (node.type === 'fibre-flow-cable') {\n const data = node.data as Partial<FibreFlowCableNodeData>;\n return (\n typeof data.label === 'string' &&\n isRecord(data.cable) &&\n (data.side === 'left' || data.side === 'right') &&\n typeof data.rowHeight === 'number' &&\n typeof data.columnWidth === 'number' &&\n typeof data.showTubeLabels === 'boolean' &&\n typeof data.showFiberNumbers === 'boolean' &&\n isRecord(data.layout)\n );\n }\n\n if (node.type === 'fibre-flow-closure') {\n const data = node.data as Partial<FibreFlowClosureNodeData>;\n return (\n typeof data.label === 'string' &&\n typeof data.width === 'number' &&\n typeof data.height === 'number' &&\n typeof data.headerHeight === 'number'\n );\n }\n\n return false;\n};\n\nconst isFibreFlowEdgeType = (\n edgeType: NetworkEdge['type'] | undefined\n): edgeType is FibreFlowMapEdgeType => {\n return edgeType === 'fibre-flow' || edgeType === 'fibre-flow-link';\n};\n\nconst hasEdgeEndpoints = (\n edge: NetworkEdge\n): edge is NetworkEdge & { id: string; source: string; target: string } => {\n return (\n typeof edge.id === 'string' &&\n edge.id.length > 0 &&\n typeof edge.source === 'string' &&\n edge.source.length > 0 &&\n typeof edge.target === 'string' &&\n edge.target.length > 0\n );\n};\n\nconst inferFibreFlowEdgeType = (edge: NetworkEdge): FibreFlowMapEdgeType => {\n if (edge.sourceHandle === 'cable-run' || edge.targetHandle === 'cable-run') {\n return 'fibre-flow-link';\n }\n return 'fibre-flow';\n};\n\nexport const normalizeFibreFlowEdges = (\n nextEdges: NetworkEdge[],\n previousEdges: FibreFlowMapEdge[] = []\n): FibreFlowMapEdge[] => {\n const previousById = new Map(previousEdges.map((edge) => [edge.id, edge] as const));\n const normalized: FibreFlowMapEdge[] = [];\n\n nextEdges.forEach((edge) => {\n if (!hasEdgeEndpoints(edge)) {\n return;\n }\n\n const previous = previousById.get(edge.id);\n const edgeType = isFibreFlowEdgeType(edge.type)\n ? edge.type\n : previous?.type ?? inferFibreFlowEdgeType(edge);\n\n normalized.push({\n ...(previous ?? {}),\n ...edge,\n type: edgeType,\n });\n });\n\n return normalized;\n};\n\nexport interface FibreFlowMapProps {\n closures: FibreFlowClosure[];\n circuits?: FibreFlowCircuit[];\n highlightedCircuitId?: string;\n layout?: FibreFlowLayoutDirection;\n rowHeight?: number;\n tubeGap?: number;\n closureGap?: number;\n cableColumnWidth?: number;\n spliceAreaWidth?: number;\n showTubeLabels?: boolean;\n showFiberNumbers?: boolean;\n colorMode?: FibreFlowColorMode;\n showCircuitId?: boolean;\n className?: string;\n style?: React.CSSProperties;\n readOnly?: boolean;\n panOnDrag?: boolean;\n panOnScroll?: boolean;\n zoomOnScroll?: boolean;\n}\n\nconst handleIdForEndpoint = (endpoint: FibreFlowEndpoint): string => {\n const tube = endpoint.tube ?? 1;\n return `fiber-${tube}-${endpoint.fiber}`;\n};\n\n/**\n * Get fiber color from an endpoint\n */\nconst getFiberColorFromEndpoint = (endpoint: FibreFlowEndpoint): string => {\n return getFiberColor(endpoint.fiber);\n};\n\n/**\n * Check if an endpoint has a striped pattern (fibers 13-24)\n */\nconst isStripedEndpoint = (endpoint: FibreFlowEndpoint): boolean => {\n return isStriped(endpoint.fiber);\n};\n\nconst formatDistanceLabel = (distanceMeters?: number, distanceLabel?: string): string | undefined => {\n if (distanceLabel) return distanceLabel;\n if (typeof distanceMeters !== 'number' || Number.isNaN(distanceMeters)) return undefined;\n if (distanceMeters >= 1000) {\n return `${(distanceMeters / 1000).toFixed(1)} km`;\n }\n return `${Math.round(distanceMeters)} m`;\n};\n\nexport const buildFibreFlowStripeDasharray = (\n needsStripeFirstHalf: boolean,\n needsStripeSecondHalf: boolean,\n firstHalfDashPattern: string,\n secondHalfDashPattern: string,\n halfLength: number,\n approximatePathLength: number\n): string => {\n if (needsStripeFirstHalf) {\n return `${firstHalfDashPattern} ${approximatePathLength}`;\n }\n\n if (needsStripeSecondHalf) {\n // Leading 0 creates an initial gap so the solid first half is not overpainted by stripe stroke.\n return `0 ${halfLength} ${secondHalfDashPattern} ${approximatePathLength}`;\n }\n\n return '6 6';\n};\n\nconst FibreFlowEdge: React.FC<EdgeProps<FibreFlowEdgeData>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n curvature: 0.35,\n });\n\n const lossText = typeof data?.lossDb === 'number' ? `${data.lossDb.toFixed(2)} dB` : '';\n const labelText = data?.label ?? lossText;\n const sourceColor = data?.sourceColor;\n const targetColor = data?.targetColor;\n const edgeColor = data?.color ?? sourceColor ?? targetColor ?? '#94a3b8';\n const sourceStriped = data?.sourceStriped ?? false;\n const targetStriped = data?.targetStriped ?? false;\n const isHighlighted = data?.highlighted ?? true;\n const isDimmed = data?.dimmed ?? false;\n const circuitId = data?.circuitId;\n const circuitLabel = data?.circuitLabel ?? circuitId; // Use friendly label if available, fallback to ID\n const showCircuitId = data?.showCircuitId ?? false;\n\n // Check if we need a gradient (source and target colors are different)\n const needsGradient = sourceColor && targetColor && sourceColor !== targetColor;\n \n // Calculate gradient stop position based on label position\n // Use straight-line distance approximation for bezier path\n const dx = targetX - sourceX;\n const dy = targetY - sourceY;\n const totalDistance = Math.sqrt(dx * dx + dy * dy);\n const labelDx = labelX - sourceX;\n const labelDy = labelY - sourceY;\n const labelDistance = Math.sqrt(labelDx * labelDx + labelDy * labelDy);\n const gradientStopPercent = totalDistance > 0 ? (labelDistance / totalDistance) * 100 : 50;\n const gradientId = `fibre-flow-gradient-${id}`;\n\n // Determine stripe rendering: only on the half corresponding to the striped fibre\n const needsStripeFirstHalf = sourceStriped && !targetStriped;\n const needsStripeSecondHalf = targetStriped && !sourceStriped;\n const needsStripeFull = sourceStriped && targetStriped;\n \n // Calculate approximate path length for dash array positioning\n // Bezier curves are typically 10-30% longer than straight-line distance\n // Use a conservative estimate of 1.25x for better coverage\n const approximatePathLength = totalDistance * 1.25;\n const halfLength = approximatePathLength / 2;\n \n // Calculate dash pattern for half-edge rendering\n // Each dash-gap pair is 12px (6px dash + 6px gap)\n const dashGapPair = 12;\n // Add extra pairs to ensure full coverage of the half (20% buffer)\n const numPairsWithBuffer = Math.ceil((halfLength * 1.2) / dashGapPair);\n const firstHalfDashPattern = Array(numPairsWithBuffer).fill('6 6').join(' ');\n // For second half, ensure we have enough to fully cover it (20% buffer)\n const secondHalfNumPairs = Math.ceil((halfLength * 1.2) / dashGapPair);\n const secondHalfDashPattern = Array(secondHalfNumPairs).fill('6 6').join(' ');\n\n // Calculate label dimensions based on content\n const hasCircuitId = showCircuitId && circuitLabel;\n const labelWidth = Math.max(\n labelText ? labelText.length * 6.2 + 16 : 0,\n hasCircuitId ? (circuitLabel?.length || 0) * 5.5 + 16 : 0\n );\n const labelHeight = hasCircuitId ? 32 : 16;\n\n return (\n <>\n <defs>\n {needsGradient && (\n <linearGradient \n id={gradientId} \n x1={sourceX} \n y1={sourceY} \n x2={targetX} \n y2={targetY}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\"0%\" stopColor={sourceColor} />\n <stop offset={`${gradientStopPercent}%`} stopColor={sourceColor} />\n <stop offset={`${gradientStopPercent}%`} stopColor={targetColor} />\n <stop offset=\"100%\" stopColor={targetColor} />\n </linearGradient>\n )}\n </defs>\n {needsGradient ? (\n <path\n id={id}\n d={edgePath}\n fill=\"none\"\n stroke={`url(#${gradientId})`}\n strokeWidth={isHighlighted ? 4.0 : 3.0}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n opacity={isDimmed ? 0.25 : 1.0}\n strokeOpacity={isDimmed ? 0.25 : 1.0}\n style={{\n mixBlendMode: 'normal',\n }}\n />\n ) : (\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: edgeColor,\n strokeWidth: isHighlighted ? 4.0 : 3.0, // Increased for better visibility and solid appearance\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n opacity: isDimmed ? 0.25 : 1.0, // Full opacity for highlighted, increased for dimmed\n strokeOpacity: isDimmed ? 0.25 : 1.0, // SVG-specific opacity for better rendering\n mixBlendMode: 'normal', // Ensure normal blending mode\n }}\n />\n )}\n {/* Stripe overlay - conditionally rendered on appropriate half */}\n {(needsStripeFull || needsStripeFirstHalf || needsStripeSecondHalf) && (\n <path\n id={`${id}-stripe`}\n d={edgePath}\n fill=\"none\"\n stroke=\"#000\"\n strokeWidth={isHighlighted ? 1.6 : 1.3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={\n buildFibreFlowStripeDasharray(\n needsStripeFirstHalf,\n needsStripeSecondHalf,\n firstHalfDashPattern,\n secondHalfDashPattern,\n halfLength,\n approximatePathLength\n )\n }\n strokeDashoffset={0}\n opacity={isDimmed ? 0.2 : 0.9}\n style={{\n mixBlendMode: 'normal',\n }}\n />\n )}\n {(labelText || hasCircuitId) && isHighlighted && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n width: labelWidth,\n height: labelHeight,\n background: 'rgba(248, 250, 252, 0.92)',\n border: '1px solid rgba(15, 23, 42, 0.4)',\n borderRadius: 4,\n fontSize: 10,\n fontFamily: 'monospace',\n color: 'rgba(15, 23, 42, 0.9)',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n pointerEvents: 'none',\n padding: '2px 4px',\n zIndex: 9999, // Ensure labels are on top of fibre edges\n }}\n >\n {labelText && (\n <div style={{ lineHeight: 1.2 }}>\n {labelText}\n </div>\n )}\n {hasCircuitId && (\n <div style={{ \n fontSize: 8, \n opacity: 0.8, \n lineHeight: 1.2,\n marginTop: labelText ? 2 : 0,\n }}>\n {circuitLabel}\n </div>\n )}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n};\n\nconst FibreFlowCableLinkEdge: React.FC<EdgeProps<FibreFlowLinkEdgeData>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n curvature: 0.2,\n });\n\n const labelText = data?.label;\n const edgeColor = data?.color ?? '#64748b';\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: edgeColor,\n strokeWidth: 3.0, // Increased for better visibility\n opacity: 0.85, // Increased opacity\n strokeDasharray: '8 10',\n }}\n />\n {labelText && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n padding: '2px 8px',\n background: 'rgba(30, 41, 59, 0.9)',\n border: `1px solid ${edgeColor}`,\n borderRadius: 10,\n fontSize: 10,\n fontFamily: 'monospace',\n color: '#e2e8f0',\n letterSpacing: 0.2,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n zIndex: 9999, // Ensure labels are on top of cable link edges\n }}\n >\n {labelText}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n};\n\nconst FibreFlowCableNode: React.FC<NodeProps<FibreFlowCableNodeData>> = ({ data }) => {\n const {\n cable,\n side,\n rowHeight,\n columnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout,\n colorMode = 'dark',\n } = data;\n \n const isLightMode = colorMode === 'light';\n\n const jacketWidth = 8;\n const handleSize = 12;\n const labelOffset = -1; // Reduced to move numbers closer to fibres\n const panelInset = 0;\n const jacketColor = cable.jacketColor ?? '#facc15';\n const hasTubes = (cable.kind ?? (cable.tubeCount ? 'tube' : 'simple')) === 'tube';\n const effectiveShowTubeLabels = showTubeLabels && hasTubes;\n\n const panelLeft = side === 'left' ? jacketWidth + panelInset : panelInset;\n const panelRight = side === 'right' ? jacketWidth + panelInset : panelInset;\n // Simple: LEFT cable = Position.Right (handles on right edge), RIGHT cable = Position.Left (handles on left edge)\n const handlePosition = side === 'left' ? Position.Right : Position.Left;\n\n const cableRunHandleStyle: React.CSSProperties = {\n width: 4,\n height: 4,\n borderRadius: '50%',\n background: jacketColor,\n border: `1px solid ${jacketColor}`,\n boxShadow: '0 0 1px rgba(0,0,0,0.4)',\n top: '50%',\n position: 'absolute',\n ...(side === 'left'\n ? { left: 0, transform: 'translate(-50%, -50%)' }\n : { right: 0, transform: 'translate(50%, -50%)' }),\n };\n\n return (\n <div\n style={{\n position: 'relative',\n width: columnWidth,\n height: layout.height,\n fontFamily: 'monospace',\n color: 'inherit',\n overflow: 'visible',\n }}\n >\n <div\n style={{\n position: 'absolute',\n top: -18,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n background: isLightMode ? 'rgba(248, 250, 252, 0.95)' : 'rgba(15, 23, 42, 0.9)',\n color: isLightMode ? '#1a1a1a' : '#f8fafc',\n padding: '2px 6px',\n borderRadius: 4,\n whiteSpace: 'nowrap',\n maxWidth: columnWidth,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 10,\n ...(side === 'right' ? { \n textAlign: 'right',\n } : {}),\n }}\n >\n {cable.label}\n </div>\n\n {/* Cable jacket container */}\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n width: jacketWidth,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n borderRadius: 4,\n background: hasTubes ? 'transparent' : jacketColor,\n border: `1px solid ${jacketColor}`,\n boxShadow: hasTubes ? 'none' : 'inset 0 0 3px rgba(0,0,0,0.3)',\n overflow: 'hidden',\n }}\n >\n {/* Individual tube segments within the cable jacket */}\n {hasTubes && layout.tubeLabels.map((tube, tubeIdx) => {\n // Find fibers in this tube\n const tubeRows = layout.rows.filter(\n (row) => row.tubeIndex === tube.tubeIndex\n );\n \n if (tubeRows.length === 0) return null;\n \n // Calculate tube segment position and height - align precisely with fibers\n const tubeTop = tubeRows[0].y;\n const tubeBottom = tubeRows[tubeRows.length - 1].y + rowHeight;\n const tubeHeight = tubeBottom - tubeTop;\n \n // Check if there's a gap after this tube (for tubeGap)\n const nextTube = layout.tubeLabels[tubeIdx + 1];\n const hasGapAfter = nextTube && (nextTube.y - tubeBottom) > 0;\n \n return (\n <div\n key={`tube-segment-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tubeTop,\n left: 0,\n right: 0,\n height: tubeHeight,\n background: tube.color,\n borderLeft: `2px solid ${tube.color}`,\n borderRight: `2px solid ${tube.color}`,\n borderTop: tubeIdx === 0 ? `2px solid ${tube.color}` : '1px solid rgba(0,0,0,0.15)',\n borderBottom: hasGapAfter ? '1px solid rgba(0,0,0,0.15)' : `2px solid ${tube.color}`,\n boxShadow: 'inset 0 0 3px rgba(0,0,0,0.1)',\n borderRadius: tubeIdx === 0 && !hasGapAfter ? '4px 4px 0 0' :\n tubeIdx === 0 ? '4px 4px 0 0' :\n !hasGapAfter ? '0 0 4px 4px' : '0',\n zIndex: 2,\n }}\n />\n );\n })}\n </div>\n\n {/* Panel border - removed background to prevent edge overlay effect */}\n {/* Only show border for visual separation without background overlay */}\n {!effectiveShowTubeLabels && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: panelLeft,\n right: panelRight,\n // Only border on the fiber side (opposite to jacket)\n // For left cable: border on right side, for right cable: border on left side\n ...(side === 'left' \n ? { borderRight: `1px solid ${jacketColor}` }\n : { borderLeft: `1px solid ${jacketColor}` }\n ),\n pointerEvents: 'none',\n zIndex: 0,\n }}\n />\n )}\n \n {/* Tube color borders wrapping around fibers with lower opacity */}\n {hasTubes && layout.tubeLabels.map((tube, _tubeIdx) => {\n // Find fibers in this tube\n const tubeRows = layout.rows.filter(\n (row) => row.tubeIndex === tube.tubeIndex\n );\n \n if (tubeRows.length === 0) return null;\n \n // Calculate tube border position and height - align with fibers\n const tubeTop = tubeRows[0].y;\n const tubeBottom = tubeRows[tubeRows.length - 1].y + rowHeight;\n const tubeHeight = tubeBottom - tubeTop;\n \n return (\n <div\n key={`tube-border-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tubeTop,\n left: panelLeft,\n right: panelRight,\n height: tubeHeight,\n // Border on the outside edge where fibers connect\n // For left cable: border on right side (outside), for right cable: border on left side (outside)\n ...(side === 'left' \n ? { borderRight: `2px solid ${tube.color}` }\n : { borderLeft: `2px solid ${tube.color}` }\n ),\n opacity: 0.5,\n pointerEvents: 'none',\n }}\n />\n );\n })}\n\n {/* Tube labels removed - not needed, saves space */}\n\n {layout.rows.map((row) => {\n const handleId = `fiber-${row.tubeIndex ?? 1}-${row.fiberIndex}`;\n const top = row.y + rowHeight / 2;\n \n // Handle style - position on edge like CouplerNode pattern\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n top: top,\n background: row.backgroundImage ? row.backgroundImage : row.color,\n backgroundColor: row.color,\n border: `2px solid ${row.color}`,\n boxShadow: '0 0 6px rgba(0,0,0,0.3)',\n // Position handle 50% over edge (centered on border) - exactly like CouplerNode\n ...(side === 'left' \n ? { right: -handleSize / 2 } // Right edge - handle center at edge, half outside\n : { left: -handleSize / 2 } // Left edge - handle center at edge, half outside\n ),\n transform: 'translateY(-50%)',\n zIndex: 1000,\n cursor: 'crosshair',\n '--fiber-bg': row.color,\n minWidth: handleSize,\n minHeight: handleSize,\n };\n\n if (row.backgroundImage) {\n handleStyle['--fiber-bg-image'] = row.backgroundImage;\n }\n\n // Position numbers inside the panel and anchor them to the fiber edge.\n // For left cables: handles are on the right edge, numbers should be to the left of handles\n // For right cables: handles are on the left edge, numbers should be to the right of handles\n // Handle is centered on edge (half outside, half inside), so position number at handleSize + offset\n const numberPosition: React.CSSProperties =\n side === 'left'\n ? { right: handleSize + labelOffset, textAlign: 'right' }\n : { left: handleSize + labelOffset, textAlign: 'left' };\n\n return (\n <React.Fragment key={row.key}>\n <Handle\n id={handleId}\n type=\"source\"\n position={handlePosition}\n className=\"fibre-flow-handle\"\n style={handleStyle}\n isConnectable={true}\n data-fiber-idx={row.fiberIndex}\n data-tube-idx={row.tubeIndex}\n data-fiber-color={row.color}\n />\n <Handle\n id={handleId}\n type=\"target\"\n position={handlePosition}\n className=\"fibre-flow-handle\"\n style={handleStyle}\n isConnectable={true}\n data-fiber-idx={row.fiberIndex}\n data-tube-idx={row.tubeIndex}\n data-fiber-color={row.color}\n />\n {showFiberNumbers && (\n <div\n style={{\n position: 'absolute',\n top: row.y + rowHeight / 2 - 6,\n ...numberPosition,\n fontSize: 8,\n fontWeight: 600,\n color: isLightMode ? 'rgba(15, 23, 42, 0.7)' : 'rgba(148, 163, 184, 0.95)',\n whiteSpace: 'nowrap',\n lineHeight: 1,\n }}\n >\n {row.fiberIndex}\n </div>\n )}\n </React.Fragment>\n );\n })}\n\n <Handle\n id=\"cable-run\"\n type=\"source\"\n position={side === 'left' ? Position.Left : Position.Right}\n className=\"cable-run-handle\"\n style={cableRunHandleStyle}\n isConnectable={true}\n data-handle-type=\"cable-run\"\n />\n <Handle\n id=\"cable-run\"\n type=\"target\"\n position={side === 'left' ? Position.Left : Position.Right}\n className=\"cable-run-handle\"\n style={cableRunHandleStyle}\n isConnectable={true}\n data-handle-type=\"cable-run\"\n />\n </div>\n );\n};\n\nconst FibreFlowClosureNode: React.FC<NodeProps<FibreFlowClosureNodeData>> = ({ data }) => {\n const isLightMode = data.colorMode === 'light';\n return (\n <div\n style={{\n width: data.width,\n height: data.height,\n // Keep the body transparent so fibre edges stay fully saturated.\n background: 'transparent',\n border: isLightMode \n ? '1px solid rgba(148, 163, 184, 0.3)'\n : '1px solid rgba(148, 163, 184, 0.5)',\n borderRadius: 12,\n boxShadow: isLightMode\n ? '0 12px 24px rgba(0, 0, 0, 0.1)'\n : '0 12px 24px rgba(15, 23, 42, 0.2)',\n position: 'relative',\n pointerEvents: 'none',\n }}\n >\n <div\n style={{\n height: data.headerHeight,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'monospace',\n fontWeight: 700,\n fontSize: 12,\n letterSpacing: 0.6,\n textTransform: 'uppercase',\n color: isLightMode ? 'rgba(15, 23, 42, 0.9)' : 'rgba(226, 232, 240, 0.9)',\n background: isLightMode ? 'rgba(241, 245, 249, 0.7)' : 'rgba(15, 23, 42, 0.6)',\n borderBottom: isLightMode \n ? '1px solid rgba(148, 163, 184, 0.2)'\n : '1px solid rgba(148, 163, 184, 0.35)',\n borderTopLeftRadius: 12,\n borderTopRightRadius: 12,\n }}\n >\n {data.label}\n </div>\n </div>\n );\n};\n\nconst buildFlowNodes = (\n closures: FibreFlowClosure[],\n layout: FibreFlowLayoutDirection,\n rowHeight: number,\n tubeGap: number,\n closureGap: number,\n cableColumnWidth: number,\n spliceAreaWidth: number,\n showTubeLabels: boolean,\n showFiberNumbers: boolean,\n colorMode: FibreFlowColorMode = 'dark'\n): FibreFlowMapNode[] => {\n const nodes: FibreFlowMapNode[] = [];\n\n let cursor = 0;\n\n closures.forEach((closure) => {\n const leftLayout = buildFibreFlowCableLayout(closure.leftCable, { rowHeight, tubeGap });\n const rightLayout = buildFibreFlowCableLayout(closure.rightCable, { rowHeight, tubeGap });\n\n const bodyHeight = Math.max(leftLayout.height, rightLayout.height);\n const bodyWidth = cableColumnWidth * 2 + spliceAreaWidth;\n const headerHeight = 32;\n const padding = 16;\n const closureWidth = bodyWidth + padding * 2;\n const closureHeight = bodyHeight + headerHeight + padding * 2;\n\n const closureId = `flow-closure-${closure.id}`;\n const leftCableId = `flow-cable-${closure.id}-left`;\n const rightCableId = `flow-cable-${closure.id}-right`;\n\n const position =\n layout === 'horizontal'\n ? { x: cursor, y: 0 }\n : { x: 0, y: cursor };\n\n cursor += (layout === 'horizontal' ? closureWidth : closureHeight) + closureGap;\n\n const headerLabel = closure.chamberId ? `${closure.id} - ${closure.chamberId}` : closure.id;\n\n nodes.push({\n id: closureId,\n type: 'fibre-flow-closure',\n position,\n data: {\n label: headerLabel,\n width: closureWidth,\n height: closureHeight,\n headerHeight,\n colorMode,\n },\n selectable: false,\n draggable: false,\n style: {\n width: closureWidth,\n height: closureHeight,\n },\n });\n\n const leftOffsetY = headerHeight + padding + (bodyHeight - leftLayout.height) / 2;\n const rightOffsetY = headerHeight + padding + (bodyHeight - rightLayout.height) / 2;\n\n nodes.push({\n id: leftCableId,\n type: 'fibre-flow-cable',\n position: { x: padding, y: leftOffsetY },\n parentId: closureId,\n extent: 'parent',\n data: {\n label: closure.leftCable.label,\n cable: closure.leftCable,\n side: 'left',\n rowHeight,\n columnWidth: cableColumnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout: leftLayout,\n colorMode,\n },\n style: {\n width: cableColumnWidth,\n height: leftLayout.height,\n },\n });\n\n nodes.push({\n id: rightCableId,\n type: 'fibre-flow-cable',\n position: { x: padding + bodyWidth - cableColumnWidth, y: rightOffsetY },\n parentId: closureId,\n extent: 'parent',\n data: {\n label: closure.rightCable.label,\n cable: closure.rightCable,\n side: 'right',\n rowHeight,\n columnWidth: cableColumnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout: rightLayout,\n colorMode,\n },\n style: {\n width: cableColumnWidth,\n height: rightLayout.height,\n },\n });\n\n });\n\n return nodes;\n};\n\nexport const buildFlowEdges = (\n closures: FibreFlowClosure[],\n circuits: FibreFlowCircuit[] | undefined,\n highlightedCircuitId: string | undefined,\n showCircuitId: boolean = false\n): FibreFlowMapEdge[] => {\n const edges: FibreFlowMapEdge[] = [];\n const circuitColorMap = new Map<string, string>();\n const circuitLabelMap = new Map<string, string>();\n const lastCableById = new Map<\n string,\n {\n nodeId: string;\n closureId: string;\n jacketColor?: string;\n distanceLabel?: string;\n distanceMeters?: number;\n }\n >();\n\n (circuits ?? []).forEach((circuit) => {\n if (circuit.color) {\n circuitColorMap.set(circuit.id, circuit.color);\n }\n if (circuit.label) {\n circuitLabelMap.set(circuit.id, circuit.label);\n }\n });\n\n closures.forEach((closure) => {\n const leftCableId = `flow-cable-${closure.id}-left`;\n const rightCableId = `flow-cable-${closure.id}-right`;\n const cables = [\n { nodeId: leftCableId, cable: closure.leftCable },\n { nodeId: rightCableId, cable: closure.rightCable },\n ];\n\n cables.forEach(({ nodeId, cable }) => {\n const previous = lastCableById.get(cable.id);\n if (previous && previous.closureId !== closure.id) {\n const label = formatDistanceLabel(\n cable.distanceMeters ?? previous.distanceMeters,\n cable.distanceLabel ?? previous.distanceLabel\n );\n const color = cable.jacketColor ?? previous.jacketColor ?? '#64748b';\n\n edges.push({\n id: `flow-link-${previous.nodeId}-${nodeId}`,\n type: 'fibre-flow-link',\n source: previous.nodeId,\n target: nodeId,\n sourceHandle: 'cable-run',\n targetHandle: 'cable-run',\n data: {\n label,\n color,\n },\n });\n }\n\n lastCableById.set(cable.id, {\n nodeId,\n closureId: closure.id,\n jacketColor: cable.jacketColor,\n distanceLabel: cable.distanceLabel,\n distanceMeters: cable.distanceMeters,\n });\n });\n\n closure.splices.forEach((splice) => {\n const isHighlighted = highlightedCircuitId\n ? splice.circuitId === highlightedCircuitId\n : true;\n const isDimmed = Boolean(highlightedCircuitId) && !isHighlighted;\n const circuitColor = splice.circuitId ? circuitColorMap.get(splice.circuitId) : undefined;\n const circuitLabel = splice.circuitId ? circuitLabelMap.get(splice.circuitId) : undefined;\n const edgeColor = splice.color ?? circuitColor;\n \n // Get source and target fiber colors\n const sourceColor = getFiberColorFromEndpoint(splice.from);\n const targetColor = getFiberColorFromEndpoint(splice.to);\n const sourceStriped = isStripedEndpoint(splice.from);\n const targetStriped = isStripedEndpoint(splice.to);\n\n edges.push({\n id: `flow-edge-${closure.id}-${splice.id}`,\n type: 'fibre-flow',\n source: leftCableId,\n target: rightCableId,\n sourceHandle: handleIdForEndpoint(splice.from),\n targetHandle: handleIdForEndpoint(splice.to),\n data: {\n lossDb: splice.lossDb,\n label: splice.label,\n color: edgeColor,\n sourceColor,\n targetColor,\n sourceStriped,\n targetStriped,\n highlighted: isHighlighted,\n dimmed: isDimmed,\n circuitId: splice.circuitId,\n circuitLabel,\n showCircuitId,\n },\n });\n });\n });\n\n return edges;\n};\n\nconst FibreFlowMapInner: React.FC<FibreFlowMapProps> = ({\n closures,\n circuits,\n highlightedCircuitId,\n layout = 'horizontal',\n rowHeight = 20,\n tubeGap = 10,\n closureGap = 140,\n cableColumnWidth = 32, // Reduced slightly: 8px jacket + 24px panel (handle 12px + number space ~12px)\n spliceAreaWidth = 260,\n showTubeLabels = true,\n showFiberNumbers = true,\n colorMode = 'dark',\n showCircuitId = false,\n className,\n style,\n readOnly = false,\n panOnDrag = true,\n panOnScroll = true,\n zoomOnScroll = true,\n}) => {\n const layoutNodes = useMemo(\n () =>\n buildFlowNodes(\n closures,\n layout,\n rowHeight,\n tubeGap,\n closureGap,\n cableColumnWidth,\n spliceAreaWidth,\n showTubeLabels,\n showFiberNumbers,\n colorMode\n ),\n [\n closures,\n layout,\n rowHeight,\n tubeGap,\n closureGap,\n cableColumnWidth,\n spliceAreaWidth,\n showTubeLabels,\n showFiberNumbers,\n colorMode,\n ]\n );\n\n const layoutEdges = useMemo(\n () => buildFlowEdges(closures, circuits, highlightedCircuitId, showCircuitId),\n [closures, circuits, highlightedCircuitId, showCircuitId]\n );\n\n const [nodes, setNodes] = useState(layoutNodes);\n const [edges, setEdges] = useState(layoutEdges);\n\n useEffect(() => {\n setNodes(layoutNodes);\n }, [layoutNodes, setNodes]);\n\n useEffect(() => {\n setEdges(layoutEdges);\n }, [layoutEdges, setEdges]);\n\n // Get fiber info (color and striped status) from a handle\n const getHandleFiberInfo = useCallback(\n (nodeId?: string | null, handleId?: string | null): { color: string; striped: boolean } | undefined => {\n if (!nodeId || !handleId || !handleId.startsWith('fiber-')) {\n return undefined;\n }\n const node = nodes.find((n) => n.id === nodeId);\n if (!node || node.type !== 'fibre-flow-cable') {\n return undefined;\n }\n const match = /^fiber-(\\d+)-(\\d+)$/.exec(handleId);\n if (!match) {\n return undefined;\n }\n const tubeIndex = Number(match[1]);\n const fiberIndex = Number(match[2]);\n const layout = (node.data as FibreFlowCableNodeData).layout;\n const row = layout.rows.find(\n (r) => (r.tubeIndex ?? 1) === tubeIndex && r.fiberIndex === fiberIndex\n );\n if (!row) {\n return undefined;\n }\n return { color: row.color, striped: row.striped ?? false };\n },\n [nodes]\n );\n\n // Validate connections - allow any fiber-to-fiber connections (any to any)\n const isValidConnection = useCallback(\n (connection: Connection): boolean => {\n if (readOnly) {\n return false;\n }\n\n if (!connection.source || !connection.target || !connection.sourceHandle || !connection.targetHandle) {\n return false;\n }\n\n // Find source and target nodes\n const sourceNode = nodes.find((n) => n.id === connection.source);\n const targetNode = nodes.find((n) => n.id === connection.target);\n\n if (!sourceNode || !targetNode) {\n return false;\n }\n\n // Check if both handles are fiber handles (format: \"fiber-<tube>-<fiber>\")\n const isSourceFiberHandle = typeof connection.sourceHandle === 'string' && connection.sourceHandle.startsWith('fiber-');\n const isTargetFiberHandle = typeof connection.targetHandle === 'string' && connection.targetHandle.startsWith('fiber-');\n const isCableRunHandle = connection.sourceHandle === 'cable-run' || connection.targetHandle === 'cable-run';\n\n // Allow cable-run connections\n if (isCableRunHandle) {\n return true;\n }\n\n // Allow any fiber-to-fiber connections (any cable to any cable)\n if (isSourceFiberHandle && isTargetFiberHandle) {\n const bothAreCables = sourceNode.type === 'fibre-flow-cable' && targetNode.type === 'fibre-flow-cable';\n return bothAreCables;\n }\n\n return false;\n },\n [nodes, readOnly]\n );\n\n const onConnect = useCallback(\n (params: Connection) => {\n if (readOnly) {\n return;\n }\n\n const isCableRun =\n params.sourceHandle === 'cable-run' || params.targetHandle === 'cable-run';\n const isFiberHandle = (handle?: string | null) =>\n typeof handle === 'string' && handle.startsWith('fiber-');\n const sourceIsFiber = isFiberHandle(params.sourceHandle);\n const targetIsFiber = isFiberHandle(params.targetHandle);\n const usesHandle = (e: Edge, nodeId?: string | null, handleId?: string | null) =>\n (e.source === nodeId && e.sourceHandle === handleId) ||\n (e.target === nodeId && e.targetHandle === handleId);\n\n // Get fiber info for manual connections\n const sourceInfo = !isCableRun ? getHandleFiberInfo(params.source, params.sourceHandle) : undefined;\n const targetInfo = !isCableRun ? getHandleFiberInfo(params.target, params.targetHandle) : undefined;\n \n const edgeData: FibreFlowEdgeData | undefined = !isCableRun\n ? {\n sourceColor: sourceInfo?.color,\n targetColor: targetInfo?.color,\n color: sourceInfo?.color ?? targetInfo?.color,\n sourceStriped: sourceInfo?.striped,\n targetStriped: targetInfo?.striped,\n }\n : undefined;\n\n setEdges((eds) => {\n const pruned = eds.filter((e) => {\n const sourceTaken = sourceIsFiber && usesHandle(e, params.source, params.sourceHandle);\n const targetTaken = targetIsFiber && usesHandle(e, params.target, params.targetHandle);\n return !(sourceTaken || targetTaken);\n });\n\n return addEdge(\n {\n ...params,\n type: isCableRun ? 'fibre-flow-link' : 'fibre-flow',\n data: edgeData,\n },\n pruned\n ) as FibreFlowMapEdge[];\n });\n },\n [getHandleFiberInfo, readOnly, setEdges]\n );\n\n // Handle edge reconnection (when dragging an edge endpoint to a new handle)\n const onEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (readOnly) {\n return;\n }\n\n const isCableRun =\n newConnection.sourceHandle === 'cable-run' || newConnection.targetHandle === 'cable-run';\n \n // Get fiber info for the new connection\n const sourceInfo = !isCableRun ? getHandleFiberInfo(newConnection.source, newConnection.sourceHandle) : undefined;\n const targetInfo = !isCableRun ? getHandleFiberInfo(newConnection.target, newConnection.targetHandle) : undefined;\n \n const edgeData: FibreFlowEdgeData | undefined = !isCableRun\n ? {\n sourceColor: sourceInfo?.color,\n targetColor: targetInfo?.color,\n color: sourceInfo?.color ?? targetInfo?.color,\n sourceStriped: sourceInfo?.striped,\n targetStriped: targetInfo?.striped,\n }\n : undefined;\n\n const isFiberHandle = (handle?: string | null) =>\n typeof handle === 'string' && handle.startsWith('fiber-');\n const usesHandle = (e: Edge, nodeId?: string | null, handleId?: string | null) =>\n (e.source === nodeId && e.sourceHandle === handleId) ||\n (e.target === nodeId && e.targetHandle === handleId);\n\n setEdges((eds) => {\n // Remove the old edge\n const withoutOld = eds.filter((e) => e.id !== oldEdge.id);\n \n // Prune edges that use the new source handle\n const sourceIsFiber = isFiberHandle(newConnection.sourceHandle);\n const targetIsFiber = isFiberHandle(newConnection.targetHandle);\n const pruned = withoutOld.filter((e) => {\n const sourceTaken = sourceIsFiber && usesHandle(e, newConnection.source, newConnection.sourceHandle);\n const targetTaken = targetIsFiber && usesHandle(e, newConnection.target, newConnection.targetHandle);\n return !(sourceTaken || targetTaken);\n });\n\n // Add the updated edge\n return addEdge(\n {\n ...newConnection,\n type: isCableRun ? 'fibre-flow-link' : 'fibre-flow',\n data: edgeData,\n },\n pruned\n ) as FibreFlowMapEdge[];\n });\n },\n [getHandleFiberInfo, readOnly, setEdges]\n );\n\n const handleNodesChange = useCallback(\n (nextNodes: NetworkNode[]) => {\n if (readOnly) {\n return;\n }\n setNodes(nextNodes.filter(isFibreFlowNode));\n },\n [readOnly, setNodes]\n );\n\n const handleEdgesChange = useCallback(\n (nextEdges: NetworkEdge[]) => {\n if (readOnly) {\n return;\n }\n setEdges((previousEdges) => normalizeFibreFlowEdges(nextEdges, previousEdges));\n },\n [readOnly, setEdges]\n );\n\n const nodeTypes = useMemo(\n () => ({\n 'fibre-flow-cable': FibreFlowCableNode,\n 'fibre-flow-closure': FibreFlowClosureNode,\n }),\n []\n );\n\n const edgeTypes = useMemo(\n () => ({\n 'fibre-flow': FibreFlowEdge,\n 'fibre-flow-link': FibreFlowCableLinkEdge,\n }),\n []\n );\n\n const wrapperStyle: React.CSSProperties = {\n borderRadius: 8,\n overflow: 'hidden',\n ...style,\n };\n\n return (\n <NetworkDiagram\n nodes={nodes}\n edges={edges}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={onConnect}\n onEdgeUpdate={onEdgeUpdate}\n isValidConnection={isValidConnection}\n connectionMode={ConnectionMode.Loose}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n className={className}\n style={wrapperStyle}\n colorMode={colorMode}\n readOnly={readOnly}\n panOnDrag={panOnDrag}\n panOnScroll={panOnScroll}\n zoomOnScroll={zoomOnScroll}\n fitViewOptions={{ padding: 0.2 }}\n />\n );\n};\n\nexport const FibreFlowMap: React.FC<FibreFlowMapProps> = (props) => {\n return <FibreFlowMapInner {...props} />;\n};\n","import React, { useMemo } from 'react';\nimport type { FibreFlowCable } from '../types/fibre-flow';\nimport { buildFibreFlowCableLayout, FibreFlowCableLayout } from '../utils/fibre-flow-layout';\n\ninterface FibreCableWithTubesExpandedProps {\n cable: FibreFlowCable;\n side: 'left' | 'right';\n rowHeight?: number;\n tubeGap?: number;\n columnWidth?: number;\n layout?: FibreFlowCableLayout;\n showTubeLabels?: boolean;\n showFiberNumbers?: boolean;\n showCableLabel?: boolean;\n}\n\nexport const FibreCableWithTubesExpanded: React.FC<FibreCableWithTubesExpandedProps> = ({\n cable,\n side,\n rowHeight = 22,\n tubeGap = 10,\n columnWidth = 150,\n layout,\n showTubeLabels,\n showFiberNumbers = true,\n showCableLabel = true,\n}) => {\n const cableLayout = useMemo(\n () => layout ?? buildFibreFlowCableLayout(cable, { rowHeight, tubeGap }),\n [layout, cable, rowHeight, tubeGap]\n );\n\n const jacketWidth = 26;\n const portSize = 10;\n const portInset = 18;\n const innerPortX = side === 'left' ? columnWidth - portInset : portInset;\n const labelOffset = 8;\n const tubeLabelX = side === 'left' ? 6 : columnWidth - jacketWidth - 18;\n const jacketColor = cable.jacketColor ?? '#facc15';\n const useTubeLabels = showTubeLabels ?? (cable.kind ?? (cable.tubeCount ? 'tube' : 'simple')) === 'tube';\n\n return (\n <div\n style={{\n position: 'relative',\n width: columnWidth,\n height: cableLayout.height,\n fontFamily: 'monospace',\n color: 'inherit',\n }}\n >\n {showCableLabel && (\n <div\n style={{\n position: 'absolute',\n top: -18,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n background: 'rgba(15, 23, 42, 0.85)',\n color: '#f8fafc',\n padding: '2px 6px',\n borderRadius: 4,\n }}\n >\n {cable.label}\n </div>\n )}\n\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n width: jacketWidth,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n borderRadius: 14,\n background: `linear-gradient(90deg, ${jacketColor} 0%, ${jacketColor} 60%, rgba(0,0,0,0.25) 100%)`,\n border: `2px solid ${jacketColor}`,\n boxShadow: 'inset 0 0 6px rgba(0,0,0,0.4)',\n }}\n />\n\n {useTubeLabels &&\n cableLayout.tubeLabels.map((tube) => (\n <div\n key={`tube-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tube.y + rowHeight / 2 - 6,\n left: tubeLabelX,\n fontSize: 9,\n fontWeight: 700,\n textTransform: 'uppercase',\n color: 'rgba(15, 23, 42, 0.75)',\n background: 'rgba(255, 255, 255, 0.6)',\n padding: '1px 6px 1px 4px',\n borderRadius: 10,\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: tube.color,\n border: '1px solid rgba(0, 0, 0, 0.4)',\n boxShadow: '0 0 3px rgba(0,0,0,0.25)',\n }}\n />\n <span>{tube.label}</span>\n </div>\n ))}\n\n {cableLayout.rows.map((row) => {\n const top = row.y + rowHeight / 2 - portSize / 2;\n const numberLeft =\n side === 'left' ? innerPortX - portSize / 2 - labelOffset : innerPortX + portSize / 2 + labelOffset;\n return (\n <React.Fragment key={row.key}>\n <div\n style={{\n position: 'absolute',\n top,\n left: innerPortX - portSize / 2,\n width: portSize,\n height: portSize,\n borderRadius: '50%',\n backgroundColor: row.color,\n backgroundImage: row.backgroundImage,\n border: '1px solid rgba(0, 0, 0, 0.4)',\n boxShadow: '0 0 4px rgba(0,0,0,0.25)',\n }}\n />\n {showFiberNumbers && (\n <div\n style={{\n position: 'absolute',\n top: row.y + rowHeight / 2 - 6,\n left: side === 'left' ? numberLeft : numberLeft,\n transform: side === 'left' ? 'translateX(-100%)' : 'none',\n fontSize: 10,\n fontWeight: 600,\n color: 'rgba(15, 23, 42, 0.75)',\n }}\n >\n {row.fiberIndex}\n </div>\n )}\n </React.Fragment>\n );\n })}\n </div>\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 {\n NetworkNode,\n NetworkEdge,\n NetBoxDevice,\n NetBoxRack,\n NetBoxCable,\n NetBoxInterface,\n NetBoxDeviceTransformOptions,\n NetBoxMappedPort,\n Port,\n PortBlock,\n PortCableType,\n PortType,\n} from '../types';\n\nconst resolveDeviceNodeId = (device: { id?: number; name: string }): string => {\n if (typeof device.id === 'number') {\n return `device-${device.id}`;\n }\n return `device-${device.name}`;\n};\n\ntype NodeStatus = 'active' | 'inactive' | 'maintenance';\ntype PortFace = 'front' | 'rear';\n\nconst DEFAULT_INTERFACE_GROUP = 'Interfaces';\nconst DEFAULT_MANAGEMENT_GROUP = 'Management';\nconst DEFAULT_POWER_GROUP = 'Power';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst toNonEmptyString = (value: unknown): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\nconst toNumber = (value: unknown): number | undefined => {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return undefined;\n};\n\nconst normalizeConnectorType = (value: unknown): Port['connectorType'] | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = value.trim().toUpperCase();\n if (normalized === 'C13' || normalized === 'C14' || normalized === 'C19' || normalized === 'C20') {\n return normalized;\n }\n return undefined;\n};\n\nconst normalizePortFace = (value: unknown): PortFace => {\n if (typeof value === 'string' && value.toLowerCase() === 'rear') {\n return 'rear';\n }\n return 'front';\n};\n\nconst getInterfaceCustomFields = (iface: NetBoxInterface): Record<string, unknown> | undefined =>\n isRecord(iface.custom_fields) ? iface.custom_fields : undefined;\n\nconst getNestedLayoutHints = (value: unknown): Record<string, unknown> | undefined =>\n isRecord(value) ? value : undefined;\n\nconst resolvePortFaceHint = (\n iface: NetBoxInterface,\n mappedFace?: NetBoxMappedPort['face']\n): PortFace => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n return normalizePortFace(\n mappedFace ??\n iface.layout?.face ??\n iface.face ??\n nestedLayout?.face ??\n customFields?.port_face ??\n customFields?.portFace ??\n customFields?.face\n );\n};\n\nconst resolvePortGroupHint = (\n iface: NetBoxInterface,\n type: PortType,\n mappedGroup?: string\n): string => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n const explicitGroup =\n toNonEmptyString(mappedGroup) ??\n toNonEmptyString(iface.layout?.group) ??\n toNonEmptyString(iface.port_group) ??\n toNonEmptyString(nestedLayout?.group) ??\n toNonEmptyString(customFields?.port_group) ??\n toNonEmptyString(customFields?.portGroup) ??\n toNonEmptyString(customFields?.interface_group) ??\n toNonEmptyString(customFields?.interfaceGroup) ??\n toNonEmptyString(customFields?.group);\n\n if (explicitGroup) {\n return explicitGroup;\n }\n if (type === 'power_ac' || type === 'power_c13' || type === 'power_c19') {\n return DEFAULT_POWER_GROUP;\n }\n if (type === 'console' || type === 'mgmt') {\n return DEFAULT_MANAGEMENT_GROUP;\n }\n return DEFAULT_INTERFACE_GROUP;\n};\n\nconst resolveConnectorTypeHint = (\n iface: NetBoxInterface,\n rawType?: string,\n mappedConnectorType?: NetBoxMappedPort['connectorType']\n): Port['connectorType'] | undefined => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n return (\n normalizeConnectorType(mappedConnectorType) ??\n normalizeConnectorType(iface.layout?.connectorType) ??\n normalizeConnectorType((iface.layout as unknown as Record<string, unknown> | undefined)?.connector_type) ??\n normalizeConnectorType(iface.connector_type) ??\n normalizeConnectorType(nestedLayout?.connectorType) ??\n normalizeConnectorType(nestedLayout?.connector_type) ??\n normalizeConnectorType(customFields?.connectorType) ??\n normalizeConnectorType(customFields?.connector_type) ??\n normalizeConnectorType(rawType)\n );\n};\n\nconst normalizePortType = (rawType: string | undefined, connectorType?: Port['connectorType']): PortType => {\n if (connectorType === 'C13') {\n return 'power_c13';\n }\n if (connectorType === 'C19') {\n return 'power_c19';\n }\n\n const normalized = (rawType ?? '').toLowerCase();\n if (normalized.includes('c13')) return 'power_c13';\n if (normalized.includes('c19')) return 'power_c19';\n if (normalized.includes('power') || normalized.includes('pdu')) return 'power_ac';\n if (\n normalized.includes('fiber') ||\n normalized.includes('sfp') ||\n normalized.includes('qsfp') ||\n normalized.includes('dac')\n ) return 'fiber';\n if (normalized.includes('console')) return 'console';\n if (normalized.includes('mgmt') || normalized.includes('management') || normalized.includes('oob')) return 'mgmt';\n if (normalized.includes('usb')) return 'usb';\n return 'ethernet';\n};\n\nconst normalizeCableType = (rawType: string | undefined): PortCableType | undefined => {\n const normalized = (rawType ?? '').toLowerCase();\n if (!normalized) return undefined;\n if (normalized.includes('om3')) return 'om3';\n if (normalized.includes('om4')) return 'om4';\n if (normalized.includes('om5')) return 'om5';\n if (normalized.includes('smf') || normalized.includes('singlemode')) return 'smf';\n if (normalized.includes('cat5e')) return 'cat5e';\n if (normalized.includes('cat6a')) return 'cat6a';\n if (normalized.includes('cat6')) return 'cat6';\n if (normalized.includes('cat7')) return 'cat7';\n if (normalized.includes('fiber') || normalized.includes('sfp') || normalized.includes('qsfp')) return 'fiber';\n if (\n normalized.includes('ethernet') ||\n normalized.includes('rj45') ||\n normalized.includes('1000base') ||\n normalized.includes('10gbase') ||\n normalized.includes('base-t')\n ) return 'ethernet';\n return undefined;\n};\n\nconst parsePortPosition = (value: unknown): Port['position'] | undefined => {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const sideRaw = value.side ?? value.port_side ?? value.portSide;\n const side =\n typeof sideRaw === 'string' &&\n ['top', 'right', 'bottom', 'left'].includes(sideRaw.toLowerCase())\n ? (sideRaw.toLowerCase() as NonNullable<Port['position']>['side'])\n : undefined;\n\n const offsetPercent = toNumber(\n value.offsetPercent ??\n value.offset_percent ??\n value.offsetPct ??\n value.offset_pct\n );\n const offsetPx = toNumber(\n value.offsetPx ??\n value.offset_px ??\n value.offsetPixels ??\n value.offset_pixels\n );\n const xPercent = toNumber(\n value.xPercent ??\n value.x_percent ??\n value.xPct ??\n value.x_pct ??\n value.horizontalPercent ??\n value.horizontal_percent ??\n value.x\n );\n const yPercent = toNumber(\n value.yPercent ??\n value.y_percent ??\n value.yPct ??\n value.y_pct ??\n value.verticalPercent ??\n value.vertical_percent ??\n value.y\n );\n\n if (\n side === undefined &&\n offsetPercent === undefined &&\n offsetPx === undefined &&\n xPercent === undefined &&\n yPercent === undefined\n ) {\n return undefined;\n }\n\n return {\n side,\n offsetPercent,\n offsetPx,\n xPercent,\n yPercent,\n };\n};\n\nconst extractMappedPosition = (\n iface: NetBoxInterface,\n mappedPort: NetBoxMappedPort | null | undefined,\n includePortPositions: boolean\n): Port['position'] | undefined => {\n if (!includePortPositions) {\n return undefined;\n }\n\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n const candidates: unknown[] = [\n mappedPort?.position,\n mappedPort,\n iface.layout?.position,\n iface.layout,\n nestedLayout?.position,\n nestedLayout,\n customFields?.port_position,\n customFields?.portPosition,\n customFields?.position,\n customFields,\n iface as unknown as Record<string, unknown>,\n ];\n\n for (const candidate of candidates) {\n const parsed = parsePortPosition(candidate);\n if (parsed) {\n return parsed;\n }\n }\n\n return undefined;\n};\n\nconst defaultMapInterfaceToPort = (\n iface: NetBoxInterface,\n includePortPositions: boolean\n): NetBoxMappedPort => {\n const rawType = iface.type?.value ?? iface.type?.label ?? iface.layout?.type ?? undefined;\n const connectorType = resolveConnectorTypeHint(iface, rawType);\n const portType = normalizePortType(rawType, connectorType);\n const group = resolvePortGroupHint(iface, portType);\n\n return {\n label: iface.name,\n face: resolvePortFaceHint(iface),\n group,\n type: portType,\n cableType: normalizeCableType(rawType),\n connected: Boolean(iface.connected_endpoint || iface.cable),\n connectorType,\n position: extractMappedPosition(iface, undefined, includePortPositions),\n };\n};\n\nconst sortInterfaces = (interfaces: NetBoxInterface[]): NetBoxInterface[] => {\n return [...interfaces].sort((a, b) => {\n const aPosition = typeof a.position === 'number' ? a.position : Number.MAX_SAFE_INTEGER;\n const bPosition = typeof b.position === 'number' ? b.position : Number.MAX_SAFE_INTEGER;\n if (aPosition !== bPosition) {\n return aPosition - bPosition;\n }\n return a.name.localeCompare(b.name);\n });\n};\n\nconst upsertPortBlock = (portBlocks: PortBlock[], name: string): PortBlock => {\n const existing = portBlocks.find((block) => block.name === name);\n if (existing) {\n return existing;\n }\n const created: PortBlock = { name, ports: [] };\n portBlocks.push(created);\n return created;\n};\n\nconst buildInterfacePortBlocks = (\n device: NetBoxDevice,\n options: NetBoxDeviceTransformOptions\n): { front: PortBlock[]; rear: PortBlock[] } => {\n const { includePortPositions = false, mapInterfaceToPort } = options;\n const front: PortBlock[] = [];\n const rear: PortBlock[] = [];\n const sortedInterfaces = sortInterfaces(device.interfaces ?? []);\n\n sortedInterfaces.forEach((iface, index) => {\n const mappedPort = mapInterfaceToPort\n ? mapInterfaceToPort({ device, iface, index })\n : defaultMapInterfaceToPort(iface, includePortPositions);\n if (!mappedPort) {\n return;\n }\n\n const rawType = mappedPort.type ?? iface.type?.value ?? iface.type?.label ?? undefined;\n const connectorType = resolveConnectorTypeHint(iface, rawType, mappedPort.connectorType);\n const type = normalizePortType(rawType, connectorType);\n const targetFace = resolvePortFaceHint(iface, mappedPort.face);\n const groupName = resolvePortGroupHint(iface, type, mappedPort.group);\n\n const block = upsertPortBlock(targetFace === 'rear' ? rear : front, groupName);\n block.ports.push({\n id: mappedPort.id,\n label: mappedPort.label ?? iface.name,\n connected: mappedPort.connected ?? Boolean(iface.connected_endpoint || iface.cable),\n type,\n cableType: normalizeCableType(mappedPort.cableType ?? iface.type?.value ?? iface.type?.label ?? undefined),\n connectorType,\n position: extractMappedPosition(iface, mappedPort, includePortPositions),\n });\n });\n\n return { front, rear };\n};\n\n/**\n * Convert NetBox rack data to NetworkNode\n */\nexport const netboxRackToNetworkNode = (rack: NetBoxRack): NetworkNode => {\n return {\n id: `rack-${rack.id}`,\n type: 'rack',\n position: { x: 0, y: 0 }, // Will be set by layout\n data: {\n label: rack.name,\n status: rack.status.value as 'active' | 'inactive' | 'maintenance',\n uHeight: rack.u_height,\n netboxId: rack.id,\n netboxType: 'rack',\n // Additional NetBox data\n facilityId: rack.facility_id,\n serial: rack.serial,\n assetTag: rack.asset_tag,\n site: rack.site.name,\n role: rack.role?.name,\n tenant: rack.tenant?.name,\n },\n };\n};\n\n/**\n * Convert NetBox device data to NetworkNode\n */\nexport const netboxDeviceToNetworkNode = (\n device: NetBoxDevice,\n options: NetBoxDeviceTransformOptions = {}\n): NetworkNode => {\n const data: NetworkNode['data'] = {\n label: device.name,\n status: device.status.value as NodeStatus,\n deviceType: device.device_type.model,\n manufacturer: device.device_type.manufacturer.name,\n role: device.device_role.name,\n uHeight: 1, // Default, should be from device type\n uPosition: device.position || 1,\n face: device.face || 'front',\n netboxId: device.id,\n netboxType: 'device',\n // Additional NetBox data\n primaryIp4: device.primary_ip4?.address,\n primaryIp6: device.primary_ip6?.address,\n site: device.site.name,\n rack: device.rack?.name,\n };\n\n if (options.includeInterfacePorts && Array.isArray(device.interfaces) && device.interfaces.length > 0) {\n const { front, rear } = buildInterfacePortBlocks(device, options);\n if (front.length > 0) {\n data.ports = front;\n }\n if (rear.length > 0) {\n data.rearPorts = rear;\n }\n }\n\n return {\n id: `device-${device.id}`,\n type: 'device',\n position: { x: 0, y: 0 }, // Will be set by layout\n parentId: device.rack ? `rack-${device.rack.id}` : undefined,\n extent: device.rack ? 'parent' : undefined,\n data,\n };\n};\n\n/**\n * Convert NetBox cable data to NetworkEdge\n */\nexport const netboxCableToNetworkEdge = (cable: NetBoxCable): NetworkEdge => {\n return {\n id: `cable-${cable.id}`,\n source: resolveDeviceNodeId(cable.termination_a.device),\n target: resolveDeviceNodeId(cable.termination_b.device),\n type: 'fiber',\n data: {\n bandwidth: cable.type.label,\n length: cable.length || 0,\n color: cable.color,\n netboxId: cable.id,\n netboxType: 'cable',\n status: cable.status.value,\n terminationA: cable.termination_a.name,\n terminationB: cable.termination_b.name,\n },\n };\n};\n\n/**\n * Convert NetBox data to network diagram format\n */\nexport const netboxToNetworkDiagram = (data: {\n racks: NetBoxRack[];\n devices: NetBoxDevice[];\n cables: NetBoxCable[];\n}, options: NetBoxDeviceTransformOptions = {}): { nodes: NetworkNode[]; edges: NetworkEdge[] } => {\n const nodes: NetworkNode[] = [];\n const edges: NetworkEdge[] = [];\n const deviceNodeIdByName = new Map<string, string>();\n\n // Convert racks\n data.racks.forEach(rack => {\n nodes.push(netboxRackToNetworkNode(rack));\n });\n\n // Convert devices\n data.devices.forEach(device => {\n const deviceNode = netboxDeviceToNetworkNode(device, options);\n nodes.push(deviceNode);\n deviceNodeIdByName.set(device.name, deviceNode.id);\n });\n\n // Convert cables\n data.cables.forEach(cable => {\n const edge = netboxCableToNetworkEdge(cable);\n const sourceId =\n (typeof cable.termination_a.device.id === 'number' ? `device-${cable.termination_a.device.id}` : undefined) ??\n deviceNodeIdByName.get(cable.termination_a.device.name) ??\n edge.source;\n const targetId =\n (typeof cable.termination_b.device.id === 'number' ? `device-${cable.termination_b.device.id}` : undefined) ??\n deviceNodeIdByName.get(cable.termination_b.device.name) ??\n edge.target;\n edges.push({\n ...edge,\n source: sourceId,\n target: targetId,\n });\n });\n\n return { nodes, edges };\n};\n\n/**\n * Calculate U position for devices in a rack\n */\nexport const calculateUPositions = (devices: NetBoxDevice[], _rackHeight: number): Map<number, number> => {\n const positions = new Map<number, number>();\n const usedPositions = new Set<number>();\n\n // Sort devices by position\n const sortedDevices = devices\n .filter(d => d.position !== null)\n .sort((a, b) => (a.position || 0) - (b.position || 0));\n\n sortedDevices.forEach(device => {\n if (device.position) {\n positions.set(device.id, device.position);\n usedPositions.add(device.position);\n }\n });\n\n return positions;\n};\n\n/**\n * Generate layout positions for nodes\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 // Position racks\n rackNodes.forEach((rack, index) => {\n rack.position = { x: index * 300, y: 100 };\n });\n\n // Position devices relative to their parent racks\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 // Position orphaned devices\n device.position = { x: Math.random() * 400 + 100, y: Math.random() * 200 + 50 };\n }\n });\n\n // Position other nodes\n otherNodes.forEach((node, index) => {\n node.position = { x: index * 150 + 100, y: 300 };\n });\n\n return nodes;\n};\n","/**\n * Generic validation result structure\n */\nexport interface PlacementValidationResult<TConflict, TOutOfBounds> {\n isValid: boolean;\n conflicts: TConflict[];\n outOfBounds: TOutOfBounds[];\n}\n\n/**\n * Options for generic placement validation\n */\nexport interface PlacementValidationOptions<TItem, TConflict, TOutOfBounds> {\n items: TItem[];\n checkOutOfBounds: (item: TItem) => { isValid: boolean; error?: TOutOfBounds } | null;\n checkConflicts: (itemA: TItem, itemB: TItem) => { hasConflict: boolean; conflict?: TConflict } | null;\n}\n\n/**\n * Generic placement validation function\n * Validates items for out-of-bounds conditions and conflicts\n * \n * @param options - Validation options including items and checker functions\n * @returns Validation result with conflicts and out-of-bounds errors\n * \n * @example\n * ```ts\n * const result = validatePlacements({\n * items: devices,\n * checkOutOfBounds: (device) => {\n * if (device.unit + device.height > rack.units) {\n * return { isValid: false, error: { deviceId: device.id, ... } };\n * }\n * return null;\n * },\n * checkConflicts: (deviceA, deviceB) => {\n * if (overlaps(deviceA, deviceB)) {\n * return { hasConflict: true, conflict: { deviceId: deviceA.id, ... } };\n * }\n * return null;\n * }\n * });\n * ```\n */\nexport function validatePlacements<TItem, TConflict, TOutOfBounds>(\n options: PlacementValidationOptions<TItem, TConflict, TOutOfBounds>\n): PlacementValidationResult<TConflict, TOutOfBounds> {\n const { items, checkOutOfBounds, checkConflicts } = options;\n const conflicts: TConflict[] = [];\n const outOfBounds: TOutOfBounds[] = [];\n \n // Check for out-of-bounds placements\n for (const item of items) {\n const boundsCheck = checkOutOfBounds(item);\n if (boundsCheck && !boundsCheck.isValid && boundsCheck.error) {\n outOfBounds.push(boundsCheck.error);\n }\n }\n \n // Check for item-to-item conflicts\n for (let i = 0; i < items.length; i++) {\n const itemA = items[i];\n \n for (let j = i + 1; j < items.length; j++) {\n const itemB = items[j];\n const conflictCheck = checkConflicts(itemA, itemB);\n \n if (conflictCheck && conflictCheck.hasConflict && conflictCheck.conflict) {\n conflicts.push(conflictCheck.conflict);\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n","import { NetworkNode, RackConfig, RackDevice, Width } from '../types';\nimport { validatePlacements } from './placement-validation';\nimport { calculateDevicePositionFromU, findNextAvailableUPosition } from './u-positioning';\nimport { isRackDeviceNodeType } from './rack-device-types';\nimport { getRackMountMode, isSplitFaceRackLayout, sharesMountedFace } from './rack-layout';\n\ntype RackMountedNodeType = 'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu';\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, RackMountedNodeType>;\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 * \n * Checks for out-of-bounds placements and device-to-device conflicts.\n * Uses the generic validatePlacements utility for consistent validation logic.\n * \n * @param rack - The rack configuration to validate\n * @param _options - Validation options (currently unused)\n * @returns Validation result with conflicts and out-of-bounds errors\n * @public\n * \n * @example\n * ```ts\n * const rack: RackConfig = {\n * id: 'rack-1',\n * units: 42,\n * devices: [\n * { id: 'dev-1', unit: 1, height: 2, ... },\n * { id: 'dev-2', unit: 2, height: 1, ... } // Conflicts with dev-1\n * ]\n * };\n * const result = validateRackDevicePlacements(rack);\n * if (!result.isValid) {\n * console.log('Conflicts:', result.conflicts);\n * }\n * ```\n */\nexport function validateRackDevicePlacements(\n rack: RackConfig,\n _options: RackSchemaOptions = {}\n): DevicePlacementValidation {\n const splitFaceLayout = isSplitFaceRackLayout(rack);\n\n return validatePlacements({\n items: rack.devices,\n checkOutOfBounds: (device) => {\n const deviceEnd = device.unit + device.height - 1;\n if (deviceEnd > rack.units) {\n return {\n isValid: false,\n error: {\n deviceId: device.id,\n uPosition: device.unit,\n uHeight: device.height,\n rackUHeight: rack.units,\n },\n };\n }\n return null;\n },\n checkConflicts: (deviceA, deviceB) => {\n const deviceAStart = deviceA.unit;\n const deviceAEnd = deviceA.unit + deviceA.height - 1;\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 if (splitFaceLayout) {\n const mountModeA = getRackMountMode(deviceA);\n const mountModeB = getRackMountMode(deviceB);\n if (!sharesMountedFace(mountModeA, mountModeB)) {\n return null;\n }\n }\n\n return {\n hasConflict: true,\n conflict: {\n deviceId: deviceA.id,\n uPosition: deviceA.unit,\n uHeight: deviceA.height,\n conflictWith: deviceB.id,\n },\n };\n }\n return null;\n },\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<RackMountedNodeType> {\n const { deviceTypeMapping = {} } = options;\n \n // Map device type to NetworkNode type\n const nodeType: RackMountedNodeType = deviceTypeMapping[device.type] || 'device';\n \n // Calculate pixel position from U position\n const position = calculateDevicePositionFromU(rack, device.unit, device.height, device);\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: device.status || 'active',\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 frontImageUrl: device.frontImageUrl,\n rearImageUrl: device.rearImageUrl,\n frontImageAttribution: device.frontImageAttribution,\n rearImageAttribution: device.rearImageAttribution,\n imageFit: device.imageFit,\n imagePosition: device.imagePosition,\n imageRepeat: device.imageRepeat,\n stretchToFit: device.stretchToFit,\n rackWidthPx: rack.data.rackWidthPx, // Pass through parent rack's custom width\n rackLayout: rack.data.rackLayout,\n rackFaceGapPx: rack.data.rackFaceGapPx,\n mountMode: getRackMountMode(device),\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 rackLayout: rack.rackLayout,\n rackFaceGapPx: rack.rackFaceGapPx,\n },\n };\n}\n\n/**\n * Build NetworkNode array from RackConfig array with comprehensive validation\n * \n * Converts rack configurations to React Flow nodes with automatic validation\n * and conflict resolution. Supports strict and nearest conflict policies.\n * \n * @param racks - Array of rack configurations\n * @param options - Build options including conflict policy and validation settings\n * @returns Array of NetworkNode objects ready for React Flow\n * @throws {DevicePlacementError} If validation fails in strict mode\n * @public\n * \n * @example\n * ```ts\n * const racks: RackConfig[] = [{\n * id: 'rack-1',\n * name: 'Main Rack',\n * units: 42,\n * devices: [...]\n * }];\n * const nodes = buildNodesFromRackConfig(racks, {\n * conflictPolicy: 'strict',\n * validatePlacements: true\n * });\n * ```\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 {\n id: device.id,\n type: 'device',\n position: { x: 0, y: 0 },\n data: {\n label: device.name,\n uHeight: device.height,\n mountMode: getRackMountMode(device),\n },\n } 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 => isRackDeviceNodeType(node.type) && 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 === Width.FULL || deviceNode.data.width === Width.HALF\n ? deviceNode.data.width\n : undefined,\n ports: Array.isArray(deviceNode.data.ports) ? deviceNode.data.ports : undefined,\n connections: deviceNode.data.connections,\n frontImageUrl: deviceNode.data.frontImageUrl,\n rearImageUrl: deviceNode.data.rearImageUrl,\n frontImageAttribution: deviceNode.data.frontImageAttribution,\n rearImageAttribution: deviceNode.data.rearImageAttribution,\n imageFit: deviceNode.data.imageFit,\n imagePosition: deviceNode.data.imagePosition,\n imageRepeat: deviceNode.data.imageRepeat,\n stretchToFit: deviceNode.data.stretchToFit,\n mountMode: getRackMountMode(deviceNode.data),\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 rackLayout: rackNode.data.rackLayout,\n rackFaceGapPx: rackNode.data.rackFaceGapPx,\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 { validatePlacements } from './placement-validation';\nimport { calculateSplicePositionFromNumberWithData, findNextAvailableHolderPosition, HOLDERS_PER_TRAY, isHolderPositionAvailable } 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 * \n * Checks for out-of-bounds placements and splice-to-splice conflicts.\n * Uses the generic validatePlacements utility for consistent validation logic.\n * \n * @param tray - The splice tray configuration to validate\n * @param _options - Validation options (currently unused)\n * @returns Validation result with conflicts and out-of-bounds errors\n * @public\n * \n * @example\n * ```ts\n * const tray: SpliceTrayConfig = {\n * id: 'tray-1',\n * splices: [\n * { id: 'splice-1', holder: 1, ... },\n * { id: 'splice-2', holder: 1, ... } // Conflicts with splice-1\n * ]\n * };\n * const result = validateSplicePlacements(tray);\n * if (!result.isValid) {\n * console.log('Conflicts:', result.conflicts);\n * }\n * ```\n */\nexport function validateSplicePlacements(\n tray: SpliceTrayConfig,\n _options: SpliceSchemaOptions = {}\n): SplicePlacementValidation {\n return validatePlacements({\n items: tray.splices,\n checkOutOfBounds: (splice) => {\n if (splice.holder < 1 || splice.holder > HOLDERS_PER_TRAY) {\n return {\n isValid: false,\n error: {\n spliceId: splice.id,\n holder: splice.holder,\n max: HOLDERS_PER_TRAY,\n },\n };\n }\n return null;\n },\n checkConflicts: (spliceA, spliceB) => {\n // Check if two splices are in the same holder position\n if (spliceA.holder === spliceB.holder) {\n return {\n hasConflict: true,\n conflict: {\n spliceId: spliceA.id,\n holder: spliceA.holder,\n conflictWith: spliceB.id,\n },\n };\n }\n return null;\n },\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 * \n * Converts splice tray configurations to React Flow nodes with automatic validation\n * and conflict resolution. Supports strict and nearest conflict policies.\n * \n * @param trays - Array of splice tray configurations\n * @param options - Build options including conflict policy and validation settings\n * @returns Array of NetworkNode objects ready for React Flow\n * @throws {SplicePlacementError} If validation fails in strict mode\n * @public\n * \n * @example\n * ```ts\n * const trays: SpliceTrayConfig[] = [{\n * id: 'tray-1',\n * name: 'Tray 1',\n * splices: [...]\n * }];\n * const nodes = buildNodesFromSpliceConfig(trays, {\n * conflictPolicy: 'strict',\n * validatePlacements: true\n * });\n * ```\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 let resolvedHolder = splice.holder;\n if (conflictPolicy === 'nearest') {\n const placeholderSplice: NetworkNode = {\n id: splice.id,\n type: 'splice',\n position: { x: 0, y: 0 },\n data: { label: splice.name, holderPosition: splice.holder },\n };\n const allNodesForConflictCheck = [...nodes, ...spliceNodes];\n if (!isHolderPositionAvailable(trayNode, placeholderSplice, splice.holder, allNodesForConflictCheck)) {\n resolvedHolder = findNextAvailableHolderPosition(trayNode, placeholderSplice, allNodesForConflictCheck, splice.holder);\n }\n }\n const adjustedSplice = resolvedHolder !== splice.holder ? { ...splice, holder: resolvedHolder } : splice;\n const spliceNode = createSpliceNode(adjustedSplice, 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 * Template Schema V2 — unified device template model.\n *\n * Supports rackable devices (1U+), 0U/unrackable devices (vertical PDUs),\n * and hybrid front/rear pass-through devices. Strictly more expressive than\n * NetBox device-type YAML while remaining import-compatible.\n *\n * @public\n */\n\nimport type { PortType, PortCableType, PortPosition } from '../types';\n\n/** Current schema version constant. */\nexport const TEMPLATE_SCHEMA_VERSION = 2;\n\n/** Device mount class — distinguishes rackable from 0U/standalone devices. */\nexport type MountClass = 'rackable' | 'zero-u';\n\n/** Device width within a rack (full 19\" or half 9.5\"). */\nexport type TemplateWidth = 'full' | 'half';\n\n/**\n * Individual port inside a template port block.\n * @public\n */\nexport interface TemplatePort {\n /** Stable identifier for the port (must be unique within the template). */\n id: string;\n /** Human-readable label. */\n label: string;\n /** Port classification for styling and validation. */\n type?: PortType;\n /** Cable type hint. */\n cableType?: PortCableType;\n /** Power connector classification. */\n connectorType?: 'C13' | 'C14' | 'C19' | 'C20' | 'AC';\n /** Explicit handle placement. */\n position?: PortPosition;\n}\n\n/**\n * Group of related ports on a single face.\n * @public\n */\nexport interface TemplatePortBlock {\n /** Group name. */\n name: string;\n /** Ports in this group. */\n ports: TemplatePort[];\n}\n\n/**\n * Per-face data container for front or rear.\n * @public\n */\nexport interface TemplateFaceData {\n /** Port blocks on this face. */\n portBlocks: TemplatePortBlock[];\n /** Optional image URL for this face. */\n imageUrl?: string;\n /** Optional attribution for the image. */\n imageAttribution?: string;\n}\n\n/**\n * Explicit front-to-rear pass-through link between ports.\n * @public\n */\nexport interface TemplateFrontRearPortLink {\n /** Port ID on the front face. */\n frontPortId: string;\n /** Port ID on the rear face. */\n rearPortId: string;\n}\n\n/**\n * Source provenance for an imported template.\n * @public\n */\nexport interface TemplateSource {\n /** Source system kind (e.g. 'netbox', 'manual'). */\n kind: string;\n /** Source repository URL. */\n repository?: string;\n /** Path within the repository. */\n path?: string;\n}\n\n/**\n * Canonical device template schema V2.\n * @public\n */\nexport interface DeviceTemplateV2 {\n /** Schema version — always 2. */\n templateSchemaVersion: 2;\n /** Unique identifier (e.g. 'cisco-c9300-48p'). */\n id: string;\n /** URL-safe slug. */\n slug: string;\n /** Device manufacturer. */\n manufacturer: string;\n /** Device model. */\n model: string;\n /** Device role (e.g. 'switch', 'pdu', 'server'). */\n role: string;\n /** Mount class — rackable (1U+) or zero-u. */\n mountClass: MountClass;\n /** Height in rack units (0 for zero-u devices). */\n uHeight: number;\n /** Width within a rack. */\n width: TemplateWidth;\n /** Per-face port and image data. */\n faces: {\n front: TemplateFaceData;\n rear: TemplateFaceData;\n };\n /** Explicit front-to-rear pass-through links. */\n frontRearPortLinks: TemplateFrontRearPortLink[];\n /** Optional image configuration. */\n images?: {\n front?: string | null;\n rear?: string | null;\n };\n /** Source provenance. */\n source?: TemplateSource;\n /** Optional tags for search/filtering. */\n tags?: string[];\n}\n\n/**\n * Single validation issue from the parser pipeline.\n * @public\n */\nexport interface TemplateValidationIssue {\n /** Severity level. */\n severity: 'error' | 'warning';\n /** Machine-readable code. */\n code: string;\n /** Human-readable description. */\n message: string;\n /** Optional path to the problematic field. */\n path?: string;\n}\n\n/**\n * Validation report emitted by the parser pipeline.\n * @public\n */\nexport interface TemplateValidationReport {\n /** Whether the template is valid (no errors — warnings are allowed). */\n valid: boolean;\n /** List of issues found. */\n issues: TemplateValidationIssue[];\n /** Summary counts per face. */\n portCounts: {\n front: number;\n rear: number;\n };\n}\n\n/**\n * Result of the full parser pipeline.\n * @public\n */\nexport interface TemplateParseResult {\n /** Parsed template (present when valid). */\n template: DeviceTemplateV2 | null;\n /** Validation report. */\n report: TemplateValidationReport;\n}\n","/**\n * NetBox → Template V2 parser pipeline.\n *\n * Five stages: Ingest → Normalize → Enrich → Validate → Export.\n *\n * **Port position semantics**: Positions use `xPercent` / `yPercent` (0-100)\n * to express where the port CENTER should be relative to the device face.\n * The renderer (`DeviceNode`) converts these to pixel coordinates and clamps\n * them so the port stays fully inside the device bounds. Clamp bounds are\n * computed from the **actual** rendered port dimensions (which vary by port\n * type — e.g., power C13/C19 connectors are larger than generic ethernet\n * handles). Templates therefore do NOT need to account for port size; the\n * renderer handles that.\n *\n * @public\n */\n\nimport type { PortType } from '../types';\nimport {\n TEMPLATE_SCHEMA_VERSION,\n type DeviceTemplateV2,\n type MountClass,\n type TemplateFaceData,\n type TemplateFrontRearPortLink,\n type TemplateParseResult,\n type TemplatePort,\n type TemplatePortBlock,\n type TemplateSource,\n type TemplateValidationIssue,\n type TemplateValidationReport,\n type TemplateWidth,\n} from './template-schema';\n\n// ---------------------------------------------------------------------------\n// Public input type — what the parser accepts as raw NetBox-style data.\n// ---------------------------------------------------------------------------\n\n/**\n * Raw port entry from a NetBox-style template.\n * @public\n */\nexport interface RawTemplatePort {\n id?: string;\n name?: string;\n label?: string;\n type?: string;\n connectorType?: string;\n connector_type?: string;\n position?: {\n side?: string;\n offsetPercent?: number;\n offset_percent?: number;\n offsetPx?: number;\n offset_px?: number;\n xPercent?: number;\n x_percent?: number;\n yPercent?: number;\n y_percent?: number;\n };\n}\n\n/**\n * Raw port block from a NetBox-style template.\n * @public\n */\nexport interface RawTemplatePortBlock {\n name?: string;\n ports?: RawTemplatePort[];\n}\n\n/**\n * Raw NetBox-style template input for the parser.\n * @public\n */\nexport interface RawNetboxTemplate {\n id?: string;\n slug?: string;\n manufacturer?: string;\n model?: string;\n role?: string;\n deviceType?: string;\n device_type?: string;\n uHeight?: number;\n u_height?: number;\n width?: string;\n ports?: RawTemplatePortBlock[];\n rearPorts?: RawTemplatePortBlock[];\n rear_ports?: RawTemplatePortBlock[];\n frontRearPortLinks?: Array<{ frontPortId?: string; rearPortId?: string; front_port_id?: string; rear_port_id?: string }>;\n front_rear_port_links?: Array<{ frontPortId?: string; rearPortId?: string; front_port_id?: string; rear_port_id?: string }>;\n frontImageUrl?: string;\n front_image_url?: string;\n rearImageUrl?: string;\n rear_image_url?: string;\n frontImageAttribution?: string;\n rearImageAttribution?: string;\n tags?: string[];\n sourceRepository?: string;\n source_repository?: string;\n sourcePath?: string;\n source_path?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst toStr = (v: unknown): string =>\n typeof v === 'string' ? v.trim() : '';\n\nconst toFiniteNumber = (v: unknown): number | undefined => {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n return undefined;\n};\n\nconst normalizeConnector = (raw: unknown): TemplatePort['connectorType'] | undefined => {\n const s = toStr(raw).toUpperCase();\n if (s === 'C13' || s === 'C14' || s === 'C19' || s === 'C20' || s === 'AC') {\n return s as TemplatePort['connectorType'];\n }\n return undefined;\n};\n\nconst normalizePortType = (rawType: string | undefined, connector?: TemplatePort['connectorType']): PortType => {\n if (connector === 'C13' || connector === 'C14') return 'power_c13';\n if (connector === 'C19' || connector === 'C20') return 'power_c19';\n if (connector === 'AC') return 'power_ac';\n\n const n = (rawType ?? '').toLowerCase();\n if (n.includes('c13')) return 'power_c13';\n if (n.includes('c19')) return 'power_c19';\n if (n.includes('power') || n.includes('pdu')) return 'power_ac';\n if (n.includes('fiber') || n.includes('sfp') || n.includes('qsfp')) return 'fiber';\n if (n.includes('console')) return 'console';\n if (n.includes('mgmt') || n.includes('management')) return 'mgmt';\n if (n.includes('usb')) return 'usb';\n return 'ethernet';\n};\n\nconst inferConnectorFromType = (portType: PortType): TemplatePort['connectorType'] | undefined => {\n if (portType === 'power_c13') return 'C13';\n if (portType === 'power_c19') return 'C19';\n if (portType === 'power_ac') return 'AC';\n return undefined;\n};\n\nconst normalizeRole = (raw: string): string =>\n raw.toLowerCase().replace(/_/g, '-').trim();\n\nconst inferMountClass = (uHeight: number): MountClass =>\n uHeight >= 1 ? 'rackable' : 'zero-u';\n\nconst normalizeWidth = (raw: string | undefined): TemplateWidth => {\n const n = (raw ?? '').toLowerCase();\n return n === 'half' ? 'half' : 'full';\n};\n\nconst generatePortId = (face: 'front' | 'rear', blockIndex: number, portIndex: number, label: string): string => {\n const safeLabel = label.replace(/[^a-zA-Z0-9_-]/g, '-').toLowerCase();\n return `${face}-b${blockIndex}-${safeLabel || `p${portIndex}`}`;\n};\n\nconst generateSlug = (manufacturer: string, model: string): string =>\n `${manufacturer}-${model}`\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n\n// ---------------------------------------------------------------------------\n// Stage A: Ingest\n// ---------------------------------------------------------------------------\n\ninterface IngestResult {\n id: string;\n slug: string;\n manufacturer: string;\n model: string;\n role: string;\n uHeight: number;\n width: string | undefined;\n frontBlocks: RawTemplatePortBlock[];\n rearBlocks: RawTemplatePortBlock[];\n rawLinks: Array<{ frontPortId?: string; rearPortId?: string }>;\n frontImageUrl?: string;\n rearImageUrl?: string;\n frontImageAttribution?: string;\n rearImageAttribution?: string;\n tags: string[];\n sourceRepository?: string;\n sourcePath?: string;\n issues: TemplateValidationIssue[];\n}\n\nfunction stageIngest(raw: RawNetboxTemplate): IngestResult {\n const issues: TemplateValidationIssue[] = [];\n\n const manufacturer = toStr(raw.manufacturer);\n const model = toStr(raw.model);\n const role = toStr(raw.role) || toStr(raw.deviceType) || toStr(raw.device_type) || 'device';\n const uHeight = toFiniteNumber(raw.uHeight) ?? toFiniteNumber(raw.u_height) ?? 0;\n\n if (!manufacturer) issues.push({ severity: 'warning', code: 'MISSING_MANUFACTURER', message: 'Template is missing manufacturer', path: 'manufacturer' });\n if (!model) issues.push({ severity: 'warning', code: 'MISSING_MODEL', message: 'Template is missing model', path: 'model' });\n\n const id = toStr(raw.id) || toStr(raw.slug) || generateSlug(manufacturer, model) || 'unknown';\n const slug = toStr(raw.slug) || generateSlug(manufacturer, model) || id;\n\n const frontBlocks = Array.isArray(raw.ports) ? raw.ports : [];\n const rearBlocks = Array.isArray(raw.rearPorts) ? raw.rearPorts : (Array.isArray(raw.rear_ports) ? raw.rear_ports : []);\n\n const rawLinks = Array.isArray(raw.frontRearPortLinks)\n ? raw.frontRearPortLinks\n : (Array.isArray(raw.front_rear_port_links) ? raw.front_rear_port_links : []);\n const normalizedLinks = rawLinks.map((link) => ({\n frontPortId: toStr(link.frontPortId) || toStr(link.front_port_id),\n rearPortId: toStr(link.rearPortId) || toStr(link.rear_port_id),\n }));\n\n return {\n id,\n slug,\n manufacturer,\n model,\n role,\n uHeight,\n width: toStr(raw.width) || undefined,\n frontBlocks,\n rearBlocks,\n rawLinks: normalizedLinks,\n frontImageUrl: toStr(raw.frontImageUrl) || toStr(raw.front_image_url) || undefined,\n rearImageUrl: toStr(raw.rearImageUrl) || toStr(raw.rear_image_url) || undefined,\n frontImageAttribution: toStr(raw.frontImageAttribution) || undefined,\n rearImageAttribution: toStr(raw.rearImageAttribution) || undefined,\n tags: Array.isArray(raw.tags) ? raw.tags.map(toStr).filter(Boolean) : [],\n sourceRepository: toStr(raw.sourceRepository) || toStr(raw.source_repository) || undefined,\n sourcePath: toStr(raw.sourcePath) || toStr(raw.source_path) || undefined,\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage B: Normalize\n// ---------------------------------------------------------------------------\n\ninterface NormalizeResult {\n role: string;\n mountClass: MountClass;\n uHeight: number;\n width: TemplateWidth;\n frontFace: TemplateFaceData;\n rearFace: TemplateFaceData;\n issues: TemplateValidationIssue[];\n}\n\nfunction normalizePortBlock(\n rawBlock: RawTemplatePortBlock,\n face: 'front' | 'rear',\n blockIndex: number\n): TemplatePortBlock {\n const name = toStr(rawBlock.name) || `Block ${blockIndex + 1}`;\n const rawPorts = Array.isArray(rawBlock.ports) ? rawBlock.ports : [];\n const ports: TemplatePort[] = rawPorts.map((rawPort, portIndex) => {\n const label = toStr(rawPort.label) || toStr(rawPort.name) || `Port ${portIndex + 1}`;\n const rawConnector = normalizeConnector(rawPort.connectorType ?? rawPort.connector_type);\n const portType = normalizePortType(toStr(rawPort.type), rawConnector);\n const connectorType = rawConnector ?? inferConnectorFromType(portType);\n const portId = toStr(rawPort.id) || generatePortId(face, blockIndex, portIndex, label);\n\n const port: TemplatePort = {\n id: portId,\n label,\n type: portType,\n connectorType,\n };\n\n if (rawPort.position) {\n const pos = rawPort.position;\n const side = toStr(pos.side) as TemplatePort['position'] extends infer P ? P extends { side?: infer S } ? S : never : never;\n const position: TemplatePort['position'] = {};\n let hasPosition = false;\n\n if (side && ['top', 'right', 'bottom', 'left'].includes(side)) {\n position.side = side as 'top' | 'right' | 'bottom' | 'left';\n hasPosition = true;\n }\n\n const offsetPercent = toFiniteNumber(pos.offsetPercent) ?? toFiniteNumber(pos.offset_percent);\n if (offsetPercent !== undefined) { position.offsetPercent = offsetPercent; hasPosition = true; }\n\n const offsetPx = toFiniteNumber(pos.offsetPx) ?? toFiniteNumber(pos.offset_px);\n if (offsetPx !== undefined) { position.offsetPx = offsetPx; hasPosition = true; }\n\n const xPercent = toFiniteNumber(pos.xPercent) ?? toFiniteNumber(pos.x_percent);\n if (xPercent !== undefined) { position.xPercent = xPercent; hasPosition = true; }\n\n const yPercent = toFiniteNumber(pos.yPercent) ?? toFiniteNumber(pos.y_percent);\n if (yPercent !== undefined) { position.yPercent = yPercent; hasPosition = true; }\n\n if (hasPosition) {\n port.position = position;\n }\n }\n\n return port;\n });\n\n return { name, ports };\n}\n\nfunction stageNormalize(ingested: IngestResult): NormalizeResult {\n const issues: TemplateValidationIssue[] = [];\n const role = normalizeRole(ingested.role);\n const uHeight = ingested.uHeight;\n const mountClass = inferMountClass(uHeight);\n const width = normalizeWidth(ingested.width);\n\n const frontPortBlocks = ingested.frontBlocks.map((block, i) => normalizePortBlock(block, 'front', i));\n const rearPortBlocks = ingested.rearBlocks.map((block, i) => normalizePortBlock(block, 'rear', i));\n\n return {\n role,\n mountClass,\n uHeight,\n width,\n frontFace: {\n portBlocks: frontPortBlocks,\n imageUrl: ingested.frontImageUrl,\n imageAttribution: ingested.frontImageAttribution,\n },\n rearFace: {\n portBlocks: rearPortBlocks,\n imageUrl: ingested.rearImageUrl,\n imageAttribution: ingested.rearImageAttribution,\n },\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage C: Enrich\n// ---------------------------------------------------------------------------\n\ninterface EnrichResult {\n frontFace: TemplateFaceData;\n rearFace: TemplateFaceData;\n mountClass: MountClass;\n role: string;\n issues: TemplateValidationIssue[];\n}\n\nfunction addFacePrefixesIfNeeded(\n frontFace: TemplateFaceData,\n rearFace: TemplateFaceData\n): { front: TemplateFaceData; rear: TemplateFaceData } {\n const frontNames = new Set(frontFace.portBlocks.map((b) => b.name));\n const rearNames = new Set(rearFace.portBlocks.map((b) => b.name));\n const overlapping = [...frontNames].filter((name) => rearNames.has(name));\n\n if (overlapping.length === 0) {\n return { front: frontFace, rear: rearFace };\n }\n\n return {\n front: {\n ...frontFace,\n portBlocks: frontFace.portBlocks.map((block) =>\n overlapping.includes(block.name) ? { ...block, name: `Front · ${block.name}` } : block\n ),\n },\n rear: {\n ...rearFace,\n portBlocks: rearFace.portBlocks.map((block) =>\n overlapping.includes(block.name) ? { ...block, name: `Rear · ${block.name}` } : block\n ),\n },\n };\n}\n\nfunction stageEnrich(normalized: NormalizeResult): EnrichResult {\n const issues: TemplateValidationIssue[] = [];\n const { front, rear } = addFacePrefixesIfNeeded(normalized.frontFace, normalized.rearFace);\n\n let role = normalized.role;\n if (!role || role === 'device') {\n const hasPowerPorts = [...front.portBlocks, ...rear.portBlocks].some((block) =>\n block.ports.some((port) => port.type && port.type.startsWith('power'))\n );\n if (hasPowerPorts && normalized.mountClass === 'zero-u') {\n role = 'pdu';\n }\n }\n\n return {\n frontFace: front,\n rearFace: rear,\n mountClass: normalized.mountClass,\n role,\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage D: Validate\n// ---------------------------------------------------------------------------\n\nfunction countFacePorts(face: TemplateFaceData): number {\n return face.portBlocks.reduce((total, block) => total + block.ports.length, 0);\n}\n\nfunction stageValidate(\n ingested: IngestResult,\n enriched: EnrichResult\n): TemplateValidationReport {\n const issues: TemplateValidationIssue[] = [];\n\n // Unique port IDs\n const allPorts: Array<{ id: string; face: string }> = [];\n for (const block of enriched.frontFace.portBlocks) {\n for (const port of block.ports) {\n allPorts.push({ id: port.id, face: 'front' });\n }\n }\n for (const block of enriched.rearFace.portBlocks) {\n for (const port of block.ports) {\n allPorts.push({ id: port.id, face: 'rear' });\n }\n }\n\n const idCounts = new Map<string, number>();\n for (const { id } of allPorts) {\n idCounts.set(id, (idCounts.get(id) ?? 0) + 1);\n }\n for (const [id, count] of idCounts) {\n if (count > 1) {\n issues.push({\n severity: 'error',\n code: 'DUPLICATE_PORT_ID',\n message: `Duplicate port id \"${id}\" found ${count} times`,\n path: `ports.${id}`,\n });\n }\n }\n\n // Count parity against raw input\n const rawFrontCount = ingested.frontBlocks.reduce(\n (total, block) => total + (Array.isArray(block.ports) ? block.ports.length : 0),\n 0\n );\n const rawRearCount = ingested.rearBlocks.reduce(\n (total, block) => total + (Array.isArray(block.ports) ? block.ports.length : 0),\n 0\n );\n const parsedFrontCount = countFacePorts(enriched.frontFace);\n const parsedRearCount = countFacePorts(enriched.rearFace);\n\n if (parsedFrontCount !== rawFrontCount) {\n issues.push({\n severity: 'error',\n code: 'FRONT_PORT_COUNT_MISMATCH',\n message: `Front port count mismatch: raw=${rawFrontCount}, parsed=${parsedFrontCount}`,\n path: 'faces.front',\n });\n }\n if (parsedRearCount !== rawRearCount) {\n issues.push({\n severity: 'error',\n code: 'REAR_PORT_COUNT_MISMATCH',\n message: `Rear port count mismatch: raw=${rawRearCount}, parsed=${parsedRearCount}`,\n path: 'faces.rear',\n });\n }\n\n // Validate pass-through links reference existing port IDs\n const allPortIds = new Set(allPorts.map((p) => p.id));\n const frontPortIds = new Set(allPorts.filter((p) => p.face === 'front').map((p) => p.id));\n const rearPortIds = new Set(allPorts.filter((p) => p.face === 'rear').map((p) => p.id));\n\n for (const link of ingested.rawLinks) {\n if (link.frontPortId && !frontPortIds.has(link.frontPortId) && !allPortIds.has(link.frontPortId)) {\n issues.push({\n severity: 'warning',\n code: 'PASS_THROUGH_FRONT_PORT_MISSING',\n message: `Pass-through link references unknown front port \"${link.frontPortId}\"`,\n path: 'frontRearPortLinks',\n });\n }\n if (link.rearPortId && !rearPortIds.has(link.rearPortId) && !allPortIds.has(link.rearPortId)) {\n issues.push({\n severity: 'warning',\n code: 'PASS_THROUGH_REAR_PORT_MISSING',\n message: `Pass-through link references unknown rear port \"${link.rearPortId}\"`,\n path: 'frontRearPortLinks',\n });\n }\n }\n\n const hasErrors = issues.some((i) => i.severity === 'error');\n\n return {\n valid: !hasErrors,\n issues,\n portCounts: {\n front: parsedFrontCount,\n rear: parsedRearCount,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage E: Export / Assemble\n// ---------------------------------------------------------------------------\n\nfunction stageExport(\n ingested: IngestResult,\n normalized: NormalizeResult,\n enriched: EnrichResult\n): DeviceTemplateV2 {\n const links: TemplateFrontRearPortLink[] = ingested.rawLinks\n .filter((link) => Boolean(link.frontPortId) && Boolean(link.rearPortId))\n .map((link) => ({\n frontPortId: link.frontPortId!,\n rearPortId: link.rearPortId!,\n }));\n\n const source: TemplateSource | undefined = ingested.sourceRepository\n ? {\n kind: 'netbox',\n repository: ingested.sourceRepository,\n path: ingested.sourcePath,\n }\n : undefined;\n\n return {\n templateSchemaVersion: TEMPLATE_SCHEMA_VERSION,\n id: ingested.id,\n slug: ingested.slug,\n manufacturer: ingested.manufacturer,\n model: ingested.model,\n role: enriched.role,\n mountClass: enriched.mountClass,\n uHeight: normalized.uHeight,\n width: normalized.width,\n faces: {\n front: enriched.frontFace,\n rear: enriched.rearFace,\n },\n frontRearPortLinks: links,\n images: {\n front: enriched.frontFace.imageUrl ?? null,\n rear: enriched.rearFace.imageUrl ?? null,\n },\n source,\n tags: ingested.tags.length > 0 ? ingested.tags : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a raw NetBox-style template through the full 5-stage pipeline.\n *\n * Returns a `TemplateParseResult` containing the validated V2 template\n * (or `null` if validation failed) and a full validation report.\n *\n * @public\n */\nexport function parseNetboxTemplate(raw: RawNetboxTemplate): TemplateParseResult {\n // Stage A\n const ingested = stageIngest(raw);\n\n // Stage B\n const normalized = stageNormalize(ingested);\n\n // Stage C\n const enriched = stageEnrich(normalized);\n\n // Stage D\n const report = stageValidate(ingested, enriched);\n report.issues.push(...ingested.issues, ...normalized.issues, ...enriched.issues);\n\n if (!report.valid) {\n return { template: null, report };\n }\n\n // Stage E\n const template = stageExport(ingested, normalized, enriched);\n\n return { template, report };\n}\n\n/**\n * Count the total number of ports on a given face of a V2 template.\n * @public\n */\nexport function countTemplateFacePorts(face: TemplateFaceData): number {\n return countFacePorts(face);\n}\n\n/**\n * Validate that rendered handle counts match the template port counts.\n * Returns issues when counts diverge — used as a regression guardrail.\n *\n * @public\n */\nexport function validateRenderFidelity(\n template: DeviceTemplateV2,\n renderedFrontHandleCount: number,\n renderedRearHandleCount: number\n): TemplateValidationIssue[] {\n const issues: TemplateValidationIssue[] = [];\n const expectedFront = countFacePorts(template.faces.front);\n const expectedRear = countFacePorts(template.faces.rear);\n\n if (renderedFrontHandleCount !== expectedFront) {\n issues.push({\n severity: 'error',\n code: 'RENDER_FRONT_COUNT_MISMATCH',\n message: `Rendered front handle count (${renderedFrontHandleCount}) does not match template (${expectedFront})`,\n path: 'faces.front',\n });\n }\n if (renderedRearHandleCount !== expectedRear) {\n issues.push({\n severity: 'error',\n code: 'RENDER_REAR_COUNT_MISMATCH',\n message: `Rendered rear handle count (${renderedRearHandleCount}) does not match template (${expectedRear})`,\n path: 'faces.rear',\n });\n }\n\n return issues;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/constants.ts","../src/utils/react-flow-theming.ts","../src/utils/rack-device-types.ts","../src/utils/rack-layout.ts","../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/utils/handle-ids.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/utils/endpoint-kind.ts","../src/core/store.ts","../src/core/hooks.ts","../src/utils/rack-geometry.ts","../src/utils/edge-connection.ts","../src/utils/rack-mount-mode.ts","../src/components/NetworkDiagram.tsx","../src/components/DiagramErrorBoundary.tsx","../src/utils/fibre-flow-layout.ts","../src/components/FibreFlowMap.tsx","../src/components/FibreCableWithTubesExpanded.tsx","../src/utils/inventory.ts","../src/utils/netbox.ts","../src/utils/placement-validation.ts","../src/utils/rack-schema.ts","../src/utils/splice-schema.ts","../src/utils/template-schema.ts","../src/utils/template-parser.ts"],"names":["U_HEIGHT_PX","RACK_HEADER_HEIGHT","RACK_WIDTH_PX","HANDLE_EXTENSION_PX","resolveSystemColorMode","colorMode","getReactFlowThemeClassName","className","themeClass","getReactFlowBackgroundColor","getReactFlowWrapperStyle","customStyle","RACK_DEVICE_NODE_TYPES","rackDeviceTypeSet","isRackDeviceNodeType","nodeType","isRackDeviceNode","node","DEFAULT_RACK_FACE_GAP_PX","getRackLayoutMode","data","isSplitFaceRackLayout","getRackFaceGapPx","getRackFaceWidthPx","getRackTotalWidthPx","faceWidth","getRackMountMode","getVisibleFacesForMountMode","mountMode","sharesMountedFace","mountModeA","mountModeB","facesA","face","getRackDeviceXPosition","rackData","deviceData","getRackDeviceBodyWidthPx","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","splitFaceLayout","deviceMountMode","otherDevice","otherUPosition","otherUHeight","newDeviceStart","newDeviceEnd","otherDeviceStart","otherDeviceEnd","otherMountMode","startFrom","u","calculateDevicePositionFromU","deviceHeight","deviceY","updateDeviceUPosition","newUPosition","normalizedPorts","validateAndSnapDevice","currentUPosition","validUPosition","getStatusColor","status","RackNode","selected","id","onViewChange","onRackFaceChange","isDragOver","label","ports","customHeaderText","effectiveWidth","faceGap","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","getFiberPaint","overrides","base","striped","backgroundImage","fiberSolidOrStriped","paint","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","isRibbon","highlight","highlightMaxWidth","baseEdgeStyle","PowerEdge","markerEnd","connectorType","metadata","customStrokeWidth","customStrokeDasharray","customOpacity","strokeWidth","strokeDasharray","renderRibbonSmoothStepEdge","getSmoothStepPath","SmoothStepFiberEdge","props","edgeStyle","ReactFlowSmoothStepEdge","getStepPath","_targetPosition","isHorizontalFirst","midX","midY","renderRibbonStepEdge","pathMatch","StepFiberEdge","_props","ThickCableEdge","_selected","Width","POWER_CONNECTORS","getPowerPortStyle","connector","isHighPower","isGenericAc","width","height","cornerStyle","getConnectorConfig","isHighPowerConnector","getPDUPortType","portIndex","getDeviceConnectorType","deviceName","name","DIRECTIONAL_HANDLE_SUFFIX","normalizeDirectionalHandleId","handleId","isPowerPortType","portType","buildPortHandleId","portBlockName","port","looksLikePowerHandleId","normalized","DISCONNECTED_PORT_COLOR","DISCONNECTED_PORT_BORDER_COLOR","DEFAULT_CONNECTED_PORT_COLOR","FILL_BACKGROUND_SIZE","DEVICE_FACE_BORDER_PX","CONNECTED_CABLE_COLORS","URL_SCHEME_PATTERN","SAFE_DATA_IMAGE_URL_PATTERN","useIsomorphicLayoutEffect","React","normalizeDeviceType","deviceType","isRelativeUrl","url","sanitizeDeviceImageUrl","trimmed","parsedUrl","protocol","toCssUrlValue","isPowerPort","resolvePowerConnectorType","normalizedType","getHandleId","resolveCurrentFace","view","rearPorts","frontImageUrl","rearImageUrl","hasFront","hasRear","resolveBackgroundSize","imageFit","stretchToFit","getConnectedPortColor","getPortColor","getPortBlocksSignature","portBlocks","block","portsSignature","position","getBaseHandleStyle","portWidth","portHeight","portColor","borderColor","compactMinSize","getGenericPortDimensions","faceRegionWidth","clampPercent","value","clampNumber","min","max","hasAbsolutePortCoordinates","resolveAbsolutePortLayoutHints","defaultPortWidth","defaultPortHeight","entries","bottomAnchoredHandleIds","uniqueRows","entry","a","b","bottomRowY","heightByHandleId","xProximityPercent","minGapPercent","candidate","yGapPercent","minGapPx","compactHeight","resolvedHeight","mapPortSideToPosition","side","inferSideFromAbsolutePercent","xPercent","yPercent","distances","getCustomHandlePlacement","absoluteCenterYOverridePx","absoluteSideOverride","minCenterX","maxCenterX","minCenterY","maxCenterY","centerX","centerY","offsetPercent","offsetPx","rawCenterX","rawCenterY","getDistributedRowCenterX","rowIndex","rowCount","getAlternatingTopBottomPlacement","portCount","topRow","topCount","bottomCount","getAlternatingTopStackPlacement","topPaddingPx","rowGapPx","maxTopPx","secondRowTopPx","topPx","getFrontPowerHandlePlacement","powerStyle","topValue","maxTop","getFrontHandlePlacement","rightPadding","leftPx","getRearHandlePlacement","normalizedDeviceType","getHandleRoles","isPower","isConnected","isPatchPanel","DeviceNode","updateNodeInternals","useUpdateNodeInternals","manufacturer","rawPorts","rawRearPorts","rackWidthPx","imagePosition","imageRepeat","effectiveRackWidth","resolvedFace","visibleFaces","currentFace","showSplitBothFaces","rackFaceGapPx","rightFaceOffsetPx","handleLayoutSignature","resolveFaceBackgroundStyle","safeBackgroundImageUrl","frontBackgroundStyle","rearBackgroundStyle","activeBackgroundStyle","rackDeviceWidth","rackDeviceLeft","fullWidthPx","halfWidthPx","isOneUServer","statusColor","deviceContainerStyle","frontHandleIds","resolveRenderedHandleId","renderPortsFromArray","faceOffsetPx","handles","totalPortsOnFace","total","shouldLineUpDenseSwitchPortsAgainstTop","shouldAutoBottomAnchorAbsoluteRows","portBlock","actualPortWidth","actualPortHeight","heightOverride","useCompactMinSize","baseStyle","defaultPlacement","customPlacement","placement","translatedHandleStyle","renderedHandleId","roles","secondaryHandleStyle","secondaryTitle","renderedHandles","PDU_HEADER_HEIGHT","PDU_BOTTOM_PADDING","PDU_TOP_PADDING","PDU_BORDER_WIDTH","INTER_PORT_GAP_PX","INTER_GROUP_GAP_PX","MGMT_UNIT_HEIGHT_PX","inferClosestSideFromPercent","normalizeConnectorType","resolvePortConnectorType","fallback","fromConnector","type","toPduPortGroups","getConnectorSequence","count","_","explicit","buildRenderablePorts","powerPorts","customGroups","connectorSequence","flatIndex","group","fallbackType","getPortRenderHeightPx","mgmtPortIndex","getRequiredBodyHeightPx","stackHeight","buildAutoYPositions","bodyHeight","portHeights","baseGaps","totalPortHeights","totalBaseGaps","gap","requiredStackHeight","drawableHeight","startOffset","adjustedGaps","extraHeight","weights","totalWeight","weight","centers","cursor","resolveCustomPlacement","fallbackCenterY","widthPx","handleWidth","handleHeight","resolvedSide","resolvedPosition","getMgmtPortIndex","mgmtUnit","totalPorts","renderMgmtUnit","yCenter","VerticalPDU","heightCm","mgmt_unit","safePowerPorts","requestedHeightPx","minimumBodyHeightPx","bodyWidth","heightPx","autoYPositions","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","handlePosition","reverseColors","fiberIdx","fiberHandleId","connectedEdge","connectedIsRibbon","edgeColor","edgeStriped","fiberPaint","left","top","handleStyle","CableNode","providedFiberCount","cableId","rotation","containerRef","rotationDegrees","innerPaddingTop","primaryText","secondaryText","defaultCableColor","cableColor","getHandlePosition","rotationDeg","renderHandles","baseColor","handleBackground","buttonHandleId","buttonHandleSize","buttonHandleStyle","buttonHandlePosition","containerStyle","contentStyle","MultiTubeCableNode","tubeCount","rawTubeStartIndex","tubes","tubeStartIndex","totalFibers","firstTubeColor","tubeIdx","tubePaint","tubeHandleId","CouplerNode","couplerFiberCount","portLabelsLeft","portLabelsRight","normalizedFiberCount","minWidth","minHeight","totalHandlesHeight","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","calculateMaxChildRight","childNodes","maxRight","dims","childRight","calculateMaxChildBottom","maxBottom","childBottom","getPanelWidth","panelNode","getPanelHeight","getInnerContentWidth","calculateCouplerRightX","couplerWidth","calculateSlotPositionFromY","y","slotHeight","calculateYFromSlotPosition","slot","snapToCouplerPosition","coupler","panel","calculatePanelDimensions","hasTubes","hasTrays","hasCouplers","tubeWidth","contentWidth","sidePadding","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","tube","PatchPanelNode","header","dataWidth","dataHeight","isUpdatingRef","useRef","childNodesRef","filtered","dynamicDimensions","useEffect","currentWidth","currentHeight","widthDiff","heightDiff","panelWidth","panelHeight","headerHeight","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","handle","getEndpointConnectionKind","normalizedHandle","frontBlocks","rearBlocks","handleLc","isStandardNetworkHandle","isCustomPortName","isPowerEndpointHandle","defaultValidateConnection","params","ctx","fiberConnection","sourceKind","targetKind","isPowerConnection","hasPduEndpoint","normalizedSourceHandle","normalizedTargetHandle","sourceHandleAlreadyConnected","targetHandleAlreadyConnected","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","rearHandleAliasSuffix","normalizedHandleId","hasExplicitRearAlias","handleSideMap","createNetworkDiagramStore","initial","options","state","listeners","partial","l","listener","edge","getNodeParentId","legacyParent","getVisibleFaces","parentId","parentRack","hasRearPorts","hasFrontPorts","resolveEndpointVisibility","nodeId","isPowerHandle","isNetworkHandle","targetVisibility","sourceVisibility","useNetworkDiagram","store","subscribe","cb","_state","getSnapshot","useSyncExternalStore","useNodes","useSelectEdgeZIndex","getRackBounds","rackWidth","rackHeight","rackLeft","rackRight","rackTop","rackBottom","isPointInRack","point","bounds","findNearestRack","racks","nearestRack","minDistance","distance","replaceEdge","connection","edgeType","selectEdgeZIndex","findBy","matchOn","existingEdge","edgeFromAddEdge","addEdge","newEdge","zIndex","edgeWithMetadata","countPorts","hasImage","inferRackMountModeFromFaces","nodeData","resolveSplitRackMountModeForDrop","dropRelativeX","explicitMountMode","inferredMountMode","splitMidpointX","isSpliceRibbonMode","spliceNode","NodeWithDataType","children","wrapperRef","setDataTypeRef","element","parent","attempts","createNodeTypes","getDragOverRackId","isSwitchLikeNode","normalizeSwitchPortConnection","sourceHandle","targetHandle","defaultEdgeTypes","MAX_TO_IMAGE_WIDTH","MAX_TO_IMAGE_HEIGHT","MAX_TO_IMAGE_PADDING","MAX_TO_IMAGE_PIXEL_RATIO","clampNumericOption","normalizeToImageOptions","NetworkDiagramInner","initialNodes","initialEdges","externalOnNodesChange","externalOnEdgesChange","debug","onNodeClick","onEdgeClick","externalNodeTypes","externalEdgeTypes","externalOnConnect","externalOnEdgeUpdate","externalIsValidConnection","externalConnectionMode","alignRacksToBottom","reAssignable","onInit","onFlowMethods","showDownloadButton","downloadButtonPosition","downloadButtonText","downloadButtonStyle","useSmoothstepEdgesForTubes","readOnly","interaction","actionPanel","connectOnClick","panOnDrag","panOnScroll","zoomOnScroll","fitViewOptions","validateAndFilterEdges","useCallback","edgesToValidate","nodesForValidation","seenHandles","validEdges","removedEdges","isSpecialHandle","sourceHandleKey","existingSourceEdge","isSourceSpecial","targetHandleKey","existingTargetEdge","isTargetSpecial","isControlled","initialNodesForValidation","initialEdgesRaw","validatedInitialEdges","localStore","storeNodes","storeEdges","reactFlowNodes","useNodesState","reactFlowEdges","setEdges","onEdgesChange","useEdgesState","reactFlowWrapper","isMobile","setIsMobile","checkMobile","isReadOnly","interactionConfig","merged","actionPanelConfig","toObject","setViewport","setReactFlowNodes","setReactFlowEdges","getEdges","fitView","flowToScreenPosition","toPng","nodeObjects","_unused","restOptions","isDownloading","setIsDownloading","onDownload","dataUrl","link","error","dragOverRackId","setDragOverRackId","dragOverRackIdRef","onViewChangeRef","onRackFaceChangeRef","onViewChangeStable","onRackFaceChangeStable","rackId","getDragOverRackIdStable","nodeTypesRef","mergedEdgeTypes","latestNodesRef","latestEdgesRef","validated","rackBottoms","r","minBottom","baselineBottom","nextNodes","currentBottom","delta","nodesMapRef","map","getNodeById","getParentRackNode","parentNode","isSplitFaceRackNode","isSplitFaceRackDeviceNode","isPatchPanelDeviceNode","commitNodes","commitEdges","nextEdges","getAbsoluteNodePosition","x","seenParents","getRackDropPoint","absolute","deriveFiberColorFromSource","sourceNodeId","inputEdges","inputColor","fiberNumStr","fiberNum","tubeNumStr","tubeNum","edgesZIndexRef","eds","hasChanges","updated","newZIndex","updatedNodes","parentPanel","parentTray","originalNode","handleNodesChange","changes","holderPositionUpdates","uPositionUpdates","parentExtentIds","updatedChanges","change","parentClosure","snappedResult","applyNodeChanges","updatedNode","handleNodeDragStart","_event","handleNodeDrag","_nodes","dropPoint","nextRackId","currentRackId","handleNodeDragStop","absolutePosition","currentNodes","relativeToRack","baseNode","splitFaceRack","nextMountMode","initialDeviceX","nextView","candidateNode","nodesForSnapping","snapped","currentNode","handleIsValidConnection","handleConnect","normalizedParams","initialValidation","isPduSource","sourceIsPowerEndpoint","targetIsPowerEndpoint","sourceNodeData","isSwitchSource","looksLikePowerTarget","looksLikeNetworkTarget","looksLikeNetworkSource","isSwitchTarget","isPduTarget","looksLikePowerSource","isTubeToCable","isCableToTube","isTubeConnection","isButtonHandleConnection","edgeData","isRibbonSpliceTarget","isRibbonSpliceSource","targetSpliceData","sourceSpliceData","edgesToRemove","existingSpliceEdge","newEdgeId","newEdges","validation","sourceHandleAlreadyUsed","targetHandleAlreadyUsed","isSpecialHandleForReplacement","isSourceSpecialForReplacement","isTargetSpecialForReplacement","edgeToAdd","setAnimatingEdges","prev","handleEdgeUpdate","oldEdge","newConnection","normalizedConnection","hasHandleOccupancyConflict","matchesSource","matchesTarget","handleNodeClick","event","isCommandClick","selectedTarget","setSelectedNode","setSelectedEdges","nds","shouldSelect","currentView","handleNodeDoubleClick","handleEdgeClick","handlePaneClick","selectedNode","animatingEdges","useOnSelectionChange","selectedEdges","handleKeyDown","deletableEdges","edgeIdsToDelete","remainingEdges","handleConnectStart","handleType","handleConnectEnd","toggleSelectedFace","deRackSelectedDevice","edgesWithAnimation","nodesMap","sourceSide","targetSide","resolveVisibleFaces","sourceVisibleFaces","targetVisibleFaces","sourceIsPatchPanel","targetIsPatchPanel","sourceHasMismatchedSide","targetHasMismatchedSide","shouldHide","nextStyle","rest","selectedNodeForActions","selectedActionButtons","supportsRearToggle","showRearToggle","showDeRack","actionPanelPosition","wrapperRect","nodeWidth","nodeHeight","topCenterAnchor","bottomCenterAnchor","flowClassName","wrapperStyle","ReactFlow","filteredChanges","edgeToRemove","applyEdgeChanges","Background","Controls","MiniMap","Panel","NetworkDiagram","ReactFlowProvider","DiagramErrorBoundary","Component","errorInfo","buildFibreFlowCableLayout","cable","rowHeight","tubeGap","rows","tubeLabels","kind","fiberStartIndex","currentY","tubeOffset","tubeColor","fiberOffset","fiberIndex","isRecord","isFibreFlowNode","isFibreFlowEdgeType","hasEdgeEndpoints","inferFibreFlowEdgeType","normalizeFibreFlowEdges","previousEdges","previousById","previous","handleIdForEndpoint","endpoint","getFiberColorFromEndpoint","isStripedEndpoint","formatDistanceLabel","distanceMeters","distanceLabel","buildFibreFlowStripeDasharray","needsStripeFirstHalf","needsStripeSecondHalf","firstHalfDashPattern","secondHalfDashPattern","halfLength","approximatePathLength","FibreFlowEdge","lossText","labelText","sourceColor","targetColor","sourceStriped","targetStriped","isHighlighted","isDimmed","circuitId","circuitLabel","showCircuitId","needsGradient","dx","dy","totalDistance","labelDx","labelDy","labelDistance","gradientStopPercent","gradientId","needsStripeFull","dashGapPair","numPairsWithBuffer","secondHalfNumPairs","hasCircuitId","labelWidth","labelHeight","FibreFlowCableLinkEdge","FibreFlowCableNode","columnWidth","showTubeLabels","showFiberNumbers","layout","isLightMode","jacketWidth","labelOffset","panelInset","jacketColor","effectiveShowTubeLabels","panelLeft","panelRight","cableRunHandleStyle","tubeRows","row","tubeTop","tubeBottom","tubeHeight","nextTube","hasGapAfter","_tubeIdx","numberPosition","FibreFlowClosureNode","buildFlowNodes","closures","closureGap","cableColumnWidth","spliceAreaWidth","closure","leftLayout","rightLayout","closureId","leftCableId","rightCableId","headerLabel","leftOffsetY","rightOffsetY","buildFlowEdges","circuits","highlightedCircuitId","circuitColorMap","circuitLabelMap","lastCableById","circuit","circuitColor","FibreFlowMapInner","layoutNodes","layoutEdges","getHandleFiberInfo","match","isValidConnection","isSourceFiberHandle","isTargetFiberHandle","onConnect","isCableRun","isFiberHandle","sourceIsFiber","targetIsFiber","usesHandle","sourceInfo","targetInfo","pruned","sourceTaken","targetTaken","onEdgeUpdate","withoutOld","handleEdgesChange","nodeTypes","edgeTypes","ConnectionMode","FibreFlowMap","FibreCableWithTubesExpanded","showCableLabel","cableLayout","portSize","portInset","innerPortX","tubeLabelX","useTubeLabels","numberLeft","inventoryRackToNetworkNode","inventoryDeviceToNetworkNode","inventoryCableToNetworkEdge","getDeviceId","term","dev","termADeviceId","termBDeviceId","inventoryToNetworkDiagram","generateLayout","rackNodes","deviceNodes","otherNodes","resolveDeviceNodeId","DEFAULT_INTERFACE_GROUP","DEFAULT_MANAGEMENT_GROUP","DEFAULT_POWER_GROUP","toNonEmptyString","toNumber","parsed","normalizePortFace","getInterfaceCustomFields","iface","getNestedLayoutHints","resolvePortFaceHint","mappedFace","customFields","nestedLayout","resolvePortGroupHint","mappedGroup","explicitGroup","resolveConnectorTypeHint","rawType","mappedConnectorType","normalizePortType","normalizeCableType","parsePortPosition","sideRaw","extractMappedPosition","mappedPort","includePortPositions","candidates","defaultMapInterfaceToPort","sortInterfaces","interfaces","aPosition","bPosition","upsertPortBlock","existing","created","buildInterfacePortBlocks","mapInterfaceToPort","front","rear","targetFace","groupName","netboxRackToNetworkNode","netboxDeviceToNetworkNode","netboxCableToNetworkEdge","netboxToNetworkDiagram","deviceNodeIdByName","deviceNode","sourceId","targetId","calculateUPositions","devices","_rackHeight","usedPositions","d","validatePlacements","items","checkOutOfBounds","checkConflicts","conflicts","outOfBounds","item","boundsCheck","itemA","j","itemB","conflictCheck","DevicePlacementError","deviceId","conflictWith","validateRackDevicePlacements","_options","deviceA","deviceB","deviceAStart","deviceAEnd","deviceBStart","deviceBEnd","createDeviceNode","deviceTypeMapping","createRackNode","buildNodesFromRackConfig","conflictPolicy","errors","conflict","bound","rackNode","adjustedDevice","createRackConfigFromNodes","addDeviceToRack","removeDeviceFromRack","SplicePlacementError","trayId","spliceId","holder","validateSplicePlacements","spliceA","spliceB","createSpliceNode","createTrayNode","buildNodesFromSpliceConfig","spliceNodes","trayNode","resolvedHolder","placeholderSplice","allNodesForConflictCheck","adjustedSplice","createSpliceConfigFromNodes","trayNodes","splices","updateSpliceHolderPosition","newHolder","addSpliceToTray","removeSpliceFromTray","TEMPLATE_SCHEMA_VERSION","toStr","v","toFiniteNumber","normalizeConnector","raw","s","inferConnectorFromType","normalizeRole","inferMountClass","normalizeWidth","generatePortId","blockIndex","safeLabel","generateSlug","model","stageIngest","issues","role","slug","normalizedLinks","normalizePortBlock","rawBlock","rawPort","rawConnector","hasPosition","stageNormalize","ingested","mountClass","frontPortBlocks","rearPortBlocks","addFacePrefixesIfNeeded","frontFace","rearFace","frontNames","rearNames","overlapping","stageEnrich","countFacePorts","stageValidate","enriched","allPorts","idCounts","rawFrontCount","rawRearCount","parsedFrontCount","parsedRearCount","allPortIds","frontPortIds","rearPortIds","stageExport","links","source","parseNetboxTemplate","report","countTemplateFacePorts","validateRenderFidelity","template","renderedFrontHandleCount","renderedRearHandleCount","expectedFront","expectedRear"],"mappings":"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","file":"index.js","sourcesContent":["// Shared layout constants for racks/devices\n\nexport const U_HEIGHT_PX = 20; // 20px per U\nexport const RACK_HEADER_HEIGHT = 60; // Fixed rack header height in px\nexport const RACK_WIDTH_PX = 300; // Fixed rack width in px\n\n/**\n * Handle extension in pixels - handles extend this many pixels outside nodes\n * Used in dimension calculations for panels and closures\n */\nexport const HANDLE_EXTENSION_PX = 5;\n\n","/**\n * Shared React Flow theming utilities\n * Ensures consistent styling across all React Flow components in the library\n */\n\nexport type ColorMode = 'light' | 'dark' | 'system';\n\n// Re-export for convenience\nexport type { ColorMode as ReactFlowColorMode };\n\n/**\n * Resolve system color mode to light or dark based on system preference\n */\nfunction resolveSystemColorMode(colorMode: ColorMode): 'light' | 'dark' {\n if (colorMode === 'system') {\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';\n }\n // Default to dark if we can't detect system preference\n return 'dark';\n }\n return colorMode;\n}\n\n/**\n * Get the React Flow theme class name based on color mode\n */\nexport function getReactFlowThemeClassName(colorMode: ColorMode, className?: string): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n const themeClass = resolvedMode === 'light' ? 'react-flow-light' : 'react-flow-dark';\n return className ? `${themeClass} ${className}` : themeClass;\n}\n\n/**\n * Get the background color for React Flow Background component\n */\nexport function getReactFlowBackgroundColor(colorMode: ColorMode): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n return resolvedMode === 'light' ? '#e5e5e5' : '#2a2a2a';\n}\n\n/**\n * Get the wrapper div style for React Flow components\n * Provides consistent container styling\n */\nexport function getReactFlowWrapperStyle(\n colorMode: ColorMode,\n customStyle?: React.CSSProperties\n): React.CSSProperties {\n return {\n width: '100%',\n height: '100%',\n ...customStyle,\n };\n}\n\n/**\n * Get the background color for React Flow Background component with custom opacity\n */\nexport function getReactFlowBackgroundColorWithOpacity(colorMode: ColorMode, opacity: number = 0.08): string {\n const resolvedMode = resolveSystemColorMode(colorMode);\n const baseColor = resolvedMode === 'light' ? '15, 23, 42' : '148, 163, 184';\n return `rgba(${baseColor}, ${opacity})`;\n}\n","/**\n * Node types that represent rack-mounted devices with U-position behavior.\n */\nexport const RACK_DEVICE_NODE_TYPES = ['device', 'server', 'switch', 'router'] as const;\n\nexport type RackDeviceNodeType = (typeof RACK_DEVICE_NODE_TYPES)[number];\n\nconst rackDeviceTypeSet = new Set<string>(RACK_DEVICE_NODE_TYPES);\n\n/**\n * Check if a node type is rack-mountable (U-positioned) device type.\n */\nexport function isRackDeviceNodeType(nodeType: string | undefined): nodeType is RackDeviceNodeType {\n return typeof nodeType === 'string' && rackDeviceTypeSet.has(nodeType);\n}\n\n/**\n * Check if a node is a rack-mountable (U-positioned) device.\n */\nexport function isRackDeviceNode(node: { type?: string } | null | undefined): node is { type: RackDeviceNodeType } {\n return !!node && isRackDeviceNodeType(node.type);\n}\n","import type { DeviceView, RackLayoutMode, RackMountMode } from '../types';\nimport { RACK_WIDTH_PX } from './constants';\n\ninterface RackLayoutData {\n rackLayout?: RackLayoutMode;\n rackFaceGapPx?: number;\n rackWidthPx?: number;\n}\n\ninterface RackMountData {\n mountMode?: RackMountMode;\n}\n\nexport const DEFAULT_RACK_FACE_GAP_PX = 24;\n\nexport function getRackLayoutMode(data: RackLayoutData | undefined): RackLayoutMode {\n return data?.rackLayout === 'split-face' ? 'split-face' : 'single-face';\n}\n\nexport function isSplitFaceRackLayout(data: RackLayoutData | undefined): boolean {\n return getRackLayoutMode(data) === 'split-face';\n}\n\nexport function getRackFaceGapPx(data: RackLayoutData | undefined): number {\n if (typeof data?.rackFaceGapPx === 'number' && Number.isFinite(data.rackFaceGapPx) && data.rackFaceGapPx >= 0) {\n return data.rackFaceGapPx;\n }\n return DEFAULT_RACK_FACE_GAP_PX;\n}\n\nexport function getRackFaceWidthPx(data: RackLayoutData | undefined): number {\n return data?.rackWidthPx || RACK_WIDTH_PX;\n}\n\nexport function getRackTotalWidthPx(data: RackLayoutData | undefined): number {\n const faceWidth = getRackFaceWidthPx(data);\n if (!isSplitFaceRackLayout(data)) {\n return faceWidth;\n }\n return faceWidth * 2 + getRackFaceGapPx(data);\n}\n\nexport function getRackMountMode(data: RackMountData | undefined): RackMountMode {\n if (data?.mountMode === 'front' || data?.mountMode === 'rear' || data?.mountMode === 'both') {\n return data.mountMode;\n }\n return 'both';\n}\n\nexport function getVisibleFacesForMountMode(mountMode: RackMountMode): DeviceView[] {\n if (mountMode === 'front') {\n return ['front'];\n }\n if (mountMode === 'rear') {\n return ['rear'];\n }\n return ['front', 'rear'];\n}\n\nexport function sharesMountedFace(\n mountModeA: RackMountMode,\n mountModeB: RackMountMode\n): boolean {\n const facesA = new Set(getVisibleFacesForMountMode(mountModeA));\n const facesB = getVisibleFacesForMountMode(mountModeB);\n return facesB.some((face) => facesA.has(face));\n}\n\nexport function getRackDeviceXPosition(\n rackData: RackLayoutData | undefined,\n deviceData: RackMountData | undefined\n): number {\n if (!isSplitFaceRackLayout(rackData)) {\n return 0;\n }\n const mountMode = getRackMountMode(deviceData);\n // Split-face orientation: rear on left, front on right.\n if (mountMode === 'front') {\n return getRackFaceWidthPx(rackData) + getRackFaceGapPx(rackData);\n }\n return 0;\n}\n\nexport function getRackDeviceBodyWidthPx(\n rackData: RackLayoutData | undefined,\n deviceData: RackMountData | undefined\n): number {\n if (!isSplitFaceRackLayout(rackData)) {\n return getRackFaceWidthPx(rackData);\n }\n const mountMode = getRackMountMode(deviceData);\n if (mountMode === 'both') {\n return getRackTotalWidthPx(rackData);\n }\n return getRackFaceWidthPx(rackData);\n}\n","import { NetworkNode, UNumberingDirection } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\nimport { isRackDeviceNodeType } from './rack-device-types';\nimport {\n getRackDeviceXPosition,\n getRackMountMode,\n isSplitFaceRackLayout,\n sharesMountedFace,\n} from './rack-layout';\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: getRackDeviceXPosition(rack.data, device.data),\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 isRackDeviceNodeType(node.type) &&\n node.parentId === rack.id && \n node.id !== device.id\n );\n const splitFaceLayout = isSplitFaceRackLayout(rack.data);\n const deviceMountMode = getRackMountMode(device.data);\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 if (splitFaceLayout) {\n const otherMountMode = getRackMountMode(otherDevice.data);\n if (!sharesMountedFace(deviceMountMode, otherMountMode)) {\n continue;\n }\n }\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 deviceData?: Pick<NetworkNode['data'], 'mountMode'>\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: getRackDeviceXPosition(rack.data, deviceData), // Align with active rack face (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<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'>,\n rack: NetworkNode,\n newUPosition: number\n): NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'> => {\n const deviceHeight = device.data.uHeight || 1;\n const newPosition = calculateDevicePositionFromU(rack, newUPosition, deviceHeight, device.data);\n const normalizedPorts = Array.isArray(device.data.ports) ? device.data.ports : undefined;\n \n return {\n ...device,\n position: newPosition,\n data: {\n ...device.data,\n ports: normalizedPorts,\n uPosition: newUPosition,\n },\n };\n};\n\n/**\n * Validate and snap device to valid U position\n */\nexport const validateAndSnapDevice = (\n device: NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'>,\n rack: NetworkNode\n): NetworkNode<'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu'> => {\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 '#ef4444';\n case 'maintenance':\n return '#f59e0b';\n default:\n return '#6b7280';\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 } from '../utils/constants';\nimport { getRackUNumberingDirection, convertUPositionForDirection } from '../utils/u-positioning';\nimport { getStatusColor } from '../utils/status-colors';\nimport {\n getRackFaceGapPx,\n getRackFaceWidthPx,\n getRackTotalWidthPx,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\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\n/**\n * Rack visualization component with U positioning support.\n * \n * Displays a 19\" rack with configurable height, front/rear view switching,\n * and support for mounting devices at specific U positions.\n * \n * @example\n * ```tsx\n * {\n * id: 'rack-1',\n * type: 'rack',\n * position: { x: 100, y: 100 },\n * data: {\n * label: 'Main Rack',\n * uHeight: 42,\n * status: 'active'\n * }\n * }\n * ```\n * \n * @public\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 splitFaceLayout = isSplitFaceRackLayout(data);\n const effectiveWidth = getRackTotalWidthPx(data);\n const faceWidth = getRackFaceWidthPx(data);\n const faceGap = getRackFaceGapPx(data);\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 if (splitFaceLayout) {\n return;\n }\n\n const next = face === 'front' ? 'rear' : 'front';\n \n if (onRackFaceChange) {\n onRackFaceChange(id, next);\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 • {splitFaceLayout ? 'rear|front' : 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 {!splitFaceLayout && (\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 )}\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 {splitFaceLayout && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n display: 'flex',\n }}\n >\n <div\n style={{\n width: `${faceWidth}px`,\n borderRight: '1px dashed rgba(156,163,175,0.35)',\n background: 'rgba(17,24,39,0.15)',\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n paddingTop: '4px',\n fontSize: '8px',\n color: '#9ca3af',\n fontWeight: 'bold',\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Rear\n </div>\n <div style={{ width: `${faceGap}px` }} />\n <div\n style={{\n width: `${faceWidth}px`,\n borderLeft: '1px dashed rgba(156,163,175,0.35)',\n background: 'rgba(17,24,39,0.25)',\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n paddingTop: '4px',\n fontSize: '8px',\n color: '#9ca3af',\n fontWeight: 'bold',\n textTransform: 'uppercase',\n letterSpacing: '0.06em',\n }}\n >\n Front\n </div>\n </div>\n )}\n </div>\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 * Fiber paint metadata used by handle and edge rendering.\n * @public\n */\nexport interface FiberPaint {\n base: string;\n striped: boolean;\n backgroundImage?: string;\n}\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 * Resolve the visual paint for a fiber (base + optional stripe pattern).\n * By default this follows TIA-598 logic: 1-12 solid, 13-24 striped.\n * @param id - Fiber color ID (1-24)\n * @param overrides - Optional visual overrides\n * @returns Paint metadata\n * @public\n */\nexport function getFiberPaint(\n id: FiberColorId | number,\n overrides?: { base?: string; striped?: boolean }\n): FiberPaint {\n const base = overrides?.base ?? baseColorFor(id);\n const striped = overrides?.striped ?? isStriped(id);\n const backgroundImage = striped\n ? `repeating-linear-gradient(45deg, ${base} 0 6px, #000 6px 9px)`\n : undefined;\n\n return { base, striped, backgroundImage };\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 paint = getFiberPaint(id);\n if (paint.backgroundImage) {\n return {\n background: paint.base,\n backgroundImage: paint.backgroundImage,\n };\n }\n return { background: paint.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}\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\n/**\n * Fiber edge component for connecting fiber ports between nodes.\n * \n * Supports both single fiber connections with color coding and ribbon fiber\n * connections (6-12 fibers) with parallel stripe visualization.\n * \n * @example\n * ```tsx\n * {\n * id: 'edge-1',\n * source: 'node-1',\n * target: 'node-2',\n * sourceHandle: 'fiber-1',\n * targetHandle: 'fiber-2',\n * type: 'fiber',\n * data: {\n * kind: 'fiber',\n * ribbonFiberIds: [1, 2, 3, 4, 5, 6] // For ribbon mode\n * }\n * }\n * ```\n * \n * @public\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 const metadata = (data?.metadata ?? {}) as Record<string, unknown>;\n const customStrokeWidth = typeof data?.powerStrokeWidth === 'number'\n ? data.powerStrokeWidth\n : (typeof metadata.strokeWidth === 'number' ? metadata.strokeWidth : undefined);\n const customStrokeDasharray = typeof data?.powerStrokeDasharray === 'string'\n ? data.powerStrokeDasharray\n : (typeof metadata.strokeDasharray === 'string' ? metadata.strokeDasharray : undefined);\n const customOpacity = typeof data?.powerOpacity === 'number'\n ? data.powerOpacity\n : (typeof metadata.opacity === 'number' ? metadata.opacity : undefined);\n\n // Different styling for different connector types\n const getEdgeStyle = () => {\n const connectorStrokeWidth = connectorType === 'C19' ? 5 : 3;\n const strokeWidth = customStrokeWidth ?? connectorStrokeWidth;\n const strokeDasharray = customStrokeDasharray ?? (connectorType === 'C19' ? 'none' : '6,3');\n const baseStyle = {\n stroke: data?.color || '#f59e0b',\n strokeWidth,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n ...(customOpacity !== undefined ? { opacity: customOpacity } : {}),\n };\n return {\n ...baseStyle,\n strokeDasharray,\n ...style, // This includes zIndex from React Flow\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 */\nimport type {\n Connection,\n Edge as ReactFlowEdge,\n EdgeTypes,\n Node as ReactFlowNode,\n NodeTypes,\n ConnectionMode,\n FitViewOptions,\n ReactFlowInstance,\n Viewport,\n} from 'reactflow';\nimport type { FibreFlowCable } from './fibre-flow';\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\n/**\n * Cable types used for connected network ports.\n * @public\n */\nexport type PortCableType =\n | 'smf'\n | 'cat6'\n | 'om3'\n | 'om4'\n | 'om5'\n | 'cat5e'\n | 'cat6a'\n | 'cat7'\n | 'fiber'\n | 'ethernet';\n\n/**\n * Device image fit options.\n *\n * Values mirror object-fit terms for API ergonomics and are mapped to valid\n * background-size values by renderers where needed.\n *\n * @public\n */\nexport type DeviceImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n\n/**\n * Device image repeat options.\n * @public\n */\nexport type DeviceImageRepeat = 'no-repeat' | 'repeat' | 'repeat-x' | 'repeat-y';\n\n/**\n * Shared image configuration for rack-mounted devices and device nodes.\n * @public\n */\nexport interface DeviceImageOptions {\n /** Optional front image URL for device background (PNG, SVG, JPEG, etc.) */\n frontImageUrl?: string;\n /** Optional rear image URL for device background (PNG, SVG, JPEG, etc.) */\n rearImageUrl?: string;\n /** Optional attribution URL for front image (e.g. source/license link) */\n frontImageAttribution?: string;\n /** Optional attribution URL for rear image (e.g. source/license link) */\n rearImageAttribution?: string;\n /** Optional background sizing for device images */\n imageFit?: DeviceImageFit;\n /** Optional background position for device images */\n imagePosition?: string;\n /** Optional background repeat for device images */\n imageRepeat?: DeviceImageRepeat;\n /** When true, stretch device image to fill the device bounds (overrides imageFit) */\n stretchToFit?: boolean;\n}\n\n/**\n * Explicit handle placement for a device/PDU port.\n * @public\n */\nexport interface PortPosition {\n /** Handle side on the node */\n side?: 'top' | 'right' | 'bottom' | 'left';\n /** Side offset as percentage (0-100) */\n offsetPercent?: number;\n /** Side offset in pixels */\n offsetPx?: number;\n /** Absolute X position as percentage (0-100) */\n xPercent?: number;\n /** Absolute Y position as percentage (0-100) */\n yPercent?: number;\n}\n\nexport interface Port {\n /** Stable handle identifier override (defaults to `label`) */\n id?: string;\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?: PortCableType;\n /** Optional power connector type for rendering (mainly for PDU ports) */\n connectorType?: 'C13' | 'C14' | 'C19' | 'C20';\n /** Optional explicit handle placement */\n position?: PortPosition;\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 | 'fibre-flow-cable'\n | 'fibre-flow-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 * Rack rendering layout modes.\n * @public\n */\nexport type RackLayoutMode = 'single-face' | 'split-face';\n\n/**\n * Rack mounting behavior for a device.\n * @public\n */\nexport type RackMountMode = 'front' | 'rear' | 'both';\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 * Shared node data fields available across node types.\n * Specific node kinds can narrow these fields via `NetworkNodeDataByType`.\n * @public\n */\nexport interface NetworkNodeDataBase extends DeviceImageOptions {\n /** Display label for the node */\n label: string;\n /** Current status of the node/device */\n status?: DeviceStatus | string;\n /** Port configurations for device-like nodes */\n ports?: PortBlock[] | number;\n /** Rear port configurations */\n rearPorts?: PortBlock[];\n /** List of connected node IDs */\n connections?: string[];\n /** NetBox integration ID */\n netboxId?: number | string;\n /** NetBox object type */\n netboxType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Inventory integration ID */\n inventoryId?: number | string;\n /** Inventory object type */\n inventoryType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Rack height in U units */\n uHeight?: number;\n /** Device position within rack in U units */\n uPosition?: number;\n /** Current front/rear view orientation */\n view?: DeviceView;\n /** Rack face orientation */\n face?: DeviceView;\n /** Rack rendering layout mode */\n rackLayout?: RackLayoutMode;\n /** Gap in pixels between front and rear faces in split-face mode */\n rackFaceGapPx?: number;\n /** Device mount behavior within a rack */\n mountMode?: RackMountMode;\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 | number;\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 /** Optional explicit PDU connector sequence */\n portTypes?: Array<'C13' | 'C19'>;\n /** Optional grouped PDU ports (supports custom positions/types) */\n pduPortGroups?: PortBlock[];\n /** Vertical PDU width in pixels */\n widthPx?: number;\n /** Optional management unit position for vertical PDUs */\n mgmt_unit?: 'top' | 'middle' | 'bottom';\n /** U numbering direction for rack nodes */\n uNumberingDirection?: UNumberingDirection;\n /** Custom header text for rack nodes */\n customHeaderText?: string;\n /** Rack UI marker visibility */\n showUMarkers?: boolean;\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 /** Splice mode */\n mode?: 'single' | 'ribbon';\n /** Legacy ribbon flag */\n ribbon?: boolean;\n /** Ribbon fiber IDs */\n ribbonFiberIds?: 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 panel-like container nodes */\n panelWidth?: number;\n /** Height override for panel-like container nodes */\n panelHeight?: number;\n /** Width override for closure nodes */\n closureWidth?: number;\n /** Height override for closure nodes */\n closureHeight?: 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 /** Number of trays for closure nodes */\n trayCount?: 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 /** Tube index (1-based) */\n tubeIndex?: number;\n /** Tube count for multi-tube cables */\n tubeCount?: number;\n /** Tube start index for multi-tube cables */\n tubeStartIndex?: number;\n /** Number of fibers per tube */\n fibersPerTube?: number;\n /** Total fiber count for cables */\n fiberCount?: number;\n /** Cable identifier */\n cableId?: string;\n /** Primary node color override */\n color?: string;\n /** Rotation in degrees for rotatable nodes */\n rotation?: number;\n /** Tube handle orientation */\n startOn?: 'left-center' | 'left' | 'right';\n /** Rack metadata for integrations */\n facilityId?: string | number | null;\n /** Rack serial metadata */\n serial?: string | null;\n /** Asset tag metadata */\n assetTag?: string | null;\n /** Site metadata */\n site?: string;\n /** Tenant metadata */\n tenant?: string;\n /** Primary IPv4 metadata */\n primaryIp4?: string;\n /** Primary IPv6 metadata */\n primaryIp6?: string;\n /** Rack name metadata */\n rack?: string | number | null;\n /** Optional arrays used by inventory/netbox transforms */\n racks?: unknown[];\n devices?: unknown[];\n cables?: unknown[];\n /** UI color mode metadata */\n colorMode?: 'light' | 'dark' | 'system';\n /** Generic dimensions used by some helpers */\n height?: number;\n headerHeight?: number;\n /** Optional precomputed map for handle-to-face resolution */\n handleSideMap?: Record<string, DeviceView>;\n /** Additional extension metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Rack node data.\n * @public\n */\nexport interface RackNodeData extends NetworkNodeDataBase {\n ports?: number | PortBlock[];\n}\n\n/**\n * Device-like node data (servers/switches/routers/generic device).\n * @public\n */\nexport interface DeviceNodeData extends NetworkNodeDataBase {\n ports?: PortBlock[] | number;\n}\n\n/**\n * Fibre flow cable node data.\n * @public\n */\nexport interface FibreFlowCableNodeData extends NetworkNodeDataBase {\n cable: FibreFlowCable;\n side: 'left' | 'right';\n rowHeight: number;\n columnWidth: number;\n showTubeLabels: boolean;\n showFiberNumbers: boolean;\n layout: unknown;\n colorMode?: 'dark' | 'light';\n}\n\n/**\n * Fibre flow closure node data.\n * @public\n */\nexport interface FibreFlowClosureNodeData extends NetworkNodeDataBase {\n width?: number;\n height?: number;\n headerHeight?: number;\n colorMode?: 'dark' | 'light';\n}\n\n/**\n * Mapping from node type to corresponding data type.\n * @public\n */\nexport interface NetworkNodeDataByType {\n rack: RackNodeData;\n switch: DeviceNodeData;\n router: DeviceNodeData;\n server: DeviceNodeData;\n fiber: NetworkNodeDataBase;\n 'patch-panel': NetworkNodeDataBase;\n device: DeviceNodeData;\n 'vertical-pdu': NetworkNodeDataBase;\n splice: NetworkNodeDataBase;\n 'splice-tray': NetworkNodeDataBase;\n tube: NetworkNodeDataBase;\n cable: NetworkNodeDataBase;\n 'multi-tube-cable': NetworkNodeDataBase;\n coupler: NetworkNodeDataBase;\n closure: NetworkNodeDataBase;\n 'fibre-split': NetworkNodeDataBase;\n 'fibre-flow-cable': FibreFlowCableNodeData;\n 'fibre-flow-closure': FibreFlowClosureNodeData;\n}\n\n/**\n * Union of all node data variants.\n * @public\n */\nexport type NetworkNodeData = NetworkNodeDataByType[NetworkNodeType];\n\n/**\n * Network node structure with data discriminated by `type`.\n * @public\n */\nexport type NetworkNode<\n TType extends NetworkNodeType = NetworkNodeType,\n TExtra = unknown\n> = TType extends NetworkNodeType\n ? ReactFlowNode<NetworkNodeDataByType[TType] & TExtra, TType> & {\n /** Type of network node */\n type: TType;\n /** Node data and configuration */\n data: NetworkNodeDataByType[TType] & TExtra;\n }\n : never;\n\n/**\n * Network edge types\n * @public\n */\nexport type NetworkEdgeType =\n | 'fiber'\n | 'ethernet'\n | 'power'\n | 'smoothstep'\n | 'step'\n | 'thick-cable'\n | 'fibre-flow'\n | 'fibre-flow-link';\n\n/**\n * Edge data payload.\n * @public\n */\nexport interface NetworkEdgeData {\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 /** Legacy striped edge flag */\n striped?: boolean;\n /** Cable type metadata used by demos/helpers */\n cableType?: PortCableType;\n /** NetBox integration metadata */\n netboxId?: number | string;\n netboxType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Inventory integration metadata */\n inventoryId?: number | string;\n inventoryType?: 'device' | 'rack' | 'interface' | 'cable' | string;\n /** Status metadata */\n status?: string;\n /** Endpoint metadata */\n terminationA?: string;\n terminationB?: string;\n /** Optional display label for the edge */\n label?: string;\n /** Optional opacity for styling (0–1) */\n opacity?: number;\n /** Optional power edge stroke width override */\n powerStrokeWidth?: number;\n /** Optional power edge stroke dasharray override */\n powerStrokeDasharray?: string;\n /** Optional power edge opacity override (0–1) */\n powerOpacity?: number;\n /** Additional extension metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Network edge data structure\n * @public\n */\nexport type NetworkEdge<TData extends NetworkEdgeData = NetworkEdgeData> = {\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?: TData;\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 /** Rack rendering layout mode */\n rackLayout?: RackLayoutMode;\n /** Gap in pixels between front and rear faces in split-face mode */\n rackFaceGapPx?: number;\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 extends DeviceImageOptions {\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 mount behavior within a rack */\n mountMode?: RackMountMode;\n /** Device role in network */\n role?: string;\n /** Current status of the device */\n status?: DeviceStatus | 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 * Fine-grained interaction controls for network diagrams.\n * @public\n */\nexport interface NetworkDiagramInteractionOptions {\n /** Enable node dragging. */\n nodesDraggable?: boolean;\n /** Enable creating connections from node handles. */\n nodesConnectable?: boolean;\n /** Enable selecting nodes/edges. */\n elementsSelectable?: boolean;\n /** Enable keyboard/mouse focus on edges. */\n edgesFocusable?: boolean;\n /** Enable reconnecting existing edges. */\n edgesReconnectable?: boolean;\n /** Enable click-to-connect behavior on handles. */\n connectOnClick?: boolean;\n /** Enable panning by dragging the canvas. */\n panOnDrag?: boolean;\n /** Enable panning by scrolling. */\n panOnScroll?: boolean;\n /** Enable zoom via mouse wheel/trackpad scroll. */\n zoomOnScroll?: boolean;\n /** Enable pinch-zoom gestures. */\n zoomOnPinch?: boolean;\n /** Enable zoom on double click. */\n zoomOnDoubleClick?: boolean;\n /** Enable deleting selected edges with keyboard keys. */\n allowKeyboardDelete?: boolean;\n /** Show or hide the built-in React Flow controls widget. */\n showControls?: boolean;\n /** Show or hide the minimap. */\n showMiniMap?: boolean;\n /** Show or hide the interactive lock/unlock button in controls. */\n showInteractiveControl?: boolean;\n}\n\n/**\n * Selection action panel options rendered above selected racks/devices.\n * @public\n */\nexport interface NetworkDiagramActionPanelOptions {\n /** Enable or disable the floating action panel entirely. Defaults to true. */\n enabled?: boolean;\n /** Show or hide the front/rear toggle button. Defaults to true. */\n showRearToggle?: boolean;\n /** Show or hide the De-rack button for rack-mounted devices. Defaults to true. */\n showDeRack?: boolean;\n}\n\n/**\n * Serializable flow snapshot payload for save/restore helpers.\n * @public\n */\nexport interface NetworkDiagramFlowObject {\n /** Snapshot nodes */\n nodes: NetworkNode[];\n /** Snapshot edges */\n edges: NetworkEdge[];\n /** Optional viewport state */\n viewport?: Viewport;\n}\n\n/**\n * Options for exported diagram images.\n * @public\n */\nexport interface NetworkDiagramToImageOptions {\n /** Export width in px (clamped to 1-8192). */\n width?: number;\n /** Export height in px (clamped to 1-8192). */\n height?: number;\n backgroundColor?: string;\n /** Export padding in px (clamped to 0-2048). */\n padding?: number;\n /** Device pixel ratio multiplier (clamped to 0.1-4). */\n pixelRatio?: number;\n /** JPEG/WebP quality (clamped to 0-1 when used). */\n quality?: number;\n filter?: (domNode: HTMLElement) => boolean;\n}\n\n/**\n * Fit-view options that support targeting node IDs directly.\n * @public\n */\nexport interface NetworkDiagramFitViewOptions extends Omit<FitViewOptions, 'nodes'> {\n /** Optional node IDs to fit */\n nodes?: string[];\n}\n\n/**\n * Exposed methods for save/restore and export integrations.\n * @public\n */\nexport interface NetworkDiagramFlowMethods {\n toObject: () => NetworkDiagramFlowObject;\n setViewport: (viewport: Viewport) => void;\n setNodes: (nodes: NetworkNode[]) => void;\n setEdges: (edges: NetworkEdge[]) => void;\n toImage: (options?: NetworkDiagramToImageOptions) => Promise<string>;\n getNodes: () => NetworkNode[];\n getEdges: () => NetworkEdge[];\n fitView: (options?: NetworkDiagramFitViewOptions) => void;\n}\n\n/**\n * Store contract accepted by `NetworkDiagram`.\n * @public\n */\nexport interface NetworkDiagramStoreApi {\n getState: () => { nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean };\n setState: (partial: Partial<{ nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean }>) => void;\n subscribe: (listener: (state: { nodes: NetworkNode[]; edges: NetworkEdge[]; debug?: boolean }) => void) => () => void;\n selectEdgeZIndex: (edge: NetworkEdge) => number;\n validateConnection: (params: {\n source: string | null;\n target: string | null;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n }) => { valid: boolean; reason?: string };\n selectNodeById: (id: string) => NetworkNode | undefined;\n selectConnectedEdges: (nodeId: string) => NetworkEdge[];\n}\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 store?: NetworkDiagramStoreApi;\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 /** Custom React Flow node types to merge with defaults */\n nodeTypes?: NodeTypes;\n /** Custom React Flow edge types to merge with defaults */\n edgeTypes?: EdgeTypes;\n /** Optional onConnect override (React Flow connection handler) */\n onConnect?: (connection: Connection) => void;\n /** Optional onEdgeUpdate override */\n onEdgeUpdate?: (oldEdge: ReactFlowEdge, newConnection: Connection) => void;\n /** Optional isValidConnection override */\n isValidConnection?: (connection: Connection) => boolean;\n /** Optional connection mode override */\n connectionMode?: ConnectionMode;\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 /** Allow rack-mounted devices to move between racks/ungroup on drag and drop. Defaults to true. */\n reAssignable?: boolean;\n /** Color mode for the diagram */\n colorMode?: 'light' | 'dark' | 'system';\n /** Callback when React Flow instance is initialized */\n onInit?: (instance: ReactFlowInstance) => void;\n /** Callback to get React Flow methods for save/restore */\n onFlowMethods?: (methods: NetworkDiagramFlowMethods) => 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 /** Force read-only behavior for the diagram (no drag/connect/delete/reconnect/pan/zoom edits). */\n readOnly?: boolean;\n /** Centralized interaction options for consistent edit/lock behavior. */\n interaction?: NetworkDiagramInteractionOptions;\n /** Configuration for the floating action panel shown on selected rack/device nodes. */\n actionPanel?: NetworkDiagramActionPanelOptions;\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 /** Optional fitView options passed to React Flow */\n fitViewOptions?: FitViewOptions;\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' | 'AC';\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 AC: {\n type: 'AC',\n color: '#60a5fa', // Blue (generic AC/NEMA)\n borderColor: '#2563eb',\n amperage: 15,\n voltage: 120,\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 const isGenericAc = connector.type === 'AC';\n\n // Size: C13/C14 are intentionally 30% larger while keeping C19/C20 unchanged.\n const width = isHighPower ? 12 : isGenericAc ? 10 : 8 * 1.3;\n const height = isHighPower ? 10 : isGenericAc ? 7 : 5 * 1.3;\n\n // Shape: C13/C14 have chamfered corners, C19/C20 and generic AC use rounded corners.\n const cornerStyle = isHighPower || isGenericAc\n ? { borderRadius: isGenericAc ? '2px' : '3px' }\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' : isGenericAc ? '3.5px' : '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 type { Port } from '../types';\n\nconst DIRECTIONAL_HANDLE_SUFFIX = /-(source|target)$/i;\n\n/**\n * Normalize source/target directional suffixes used for bidirectional handles.\n * Example: `Rear Ports-1-target` -> `Rear Ports-1`.\n */\nexport function normalizeDirectionalHandleId(handleId: string | null | undefined): string {\n if (!handleId) return '';\n return handleId.replace(DIRECTIONAL_HANDLE_SUFFIX, '');\n}\n\n/**\n * Returns true when a port type is considered power-related.\n */\nexport function isPowerPortType(portType: string | undefined): boolean {\n return typeof portType === 'string' && portType.includes('power');\n}\n\n/**\n * Build a stable handle id for a port.\n * Power ports use the label directly to preserve legacy ids.\n */\nexport function buildPortHandleId(\n portBlockName: string,\n port: Pick<Port, 'label' | 'id'> & { type?: string }\n): string {\n if (typeof port.id === 'string' && port.id.length > 0) {\n return port.id;\n }\n return isPowerPortType(port.type) ? port.label : `${portBlockName}-${port.label}`;\n}\n\n/**\n * Heuristic for whether a handle id represents a power endpoint.\n */\nexport function looksLikePowerHandleId(handleId: string): boolean {\n const normalized = normalizeDirectionalHandleId(handleId).toLowerCase();\n return normalized.startsWith('pwr') || normalized.includes('power');\n}\n","import React from 'react';\nimport { Handle, Position, NodeProps, useUpdateNodeInternals } from 'reactflow';\nimport { NetworkNode, Width, PortBlock, Port, PortCableType, DeviceImageFit, PortPosition } from '../types';\nimport { U_HEIGHT_PX, RACK_WIDTH_PX } from '../utils/constants';\nimport { getPowerPortStyle, getDeviceConnectorType } from '../utils/power-connectors';\nimport { getStatusColor } from '../utils/status-colors';\nimport { buildPortHandleId, isPowerPortType } from '../utils/handle-ids';\nimport {\n getRackDeviceBodyWidthPx,\n getRackFaceGapPx,\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\n\ntype DeviceFace = 'front' | 'rear';\ntype HandleRole = 'source' | 'target';\n\ninterface HandlePlacement {\n position: Position;\n style: React.CSSProperties;\n}\n\ntype PortSide = NonNullable<PortPosition['side']>;\n\ntype DeviceNodeCssVars = React.CSSProperties & {\n '--rn-device-bg-image'?: string;\n '--rn-device-bg-position'?: string;\n '--rn-device-bg-repeat'?: string;\n '--rn-device-bg-size'?: string;\n '--rn-device-border-color'?: string;\n '--rn-device-box-shadow'?: string;\n '--rn-device-height'?: string;\n '--rn-device-left'?: string;\n '--rn-device-status-color'?: string;\n '--rn-device-translate-y'?: string;\n '--rn-device-width'?: string;\n};\n\nconst DISCONNECTED_PORT_COLOR = '#6b7280';\nconst DISCONNECTED_PORT_BORDER_COLOR = '#374151';\nconst DEFAULT_CONNECTED_PORT_COLOR = '#10b981';\nconst FILL_BACKGROUND_SIZE = '100% 100%';\nconst DEVICE_FACE_BORDER_PX = 1;\n\nconst CONNECTED_CABLE_COLORS: Record<PortCableType, string> = {\n smf: '#fbbf24',\n cat6: '#8b5cf6',\n om3: '#06b6d4',\n om4: '#8b5cf6',\n om5: '#84cc16',\n cat5e: '#3b82f6',\n cat6a: '#ef4444',\n cat7: '#f97316',\n fiber: '#3b82f6',\n ethernet: '#10b981',\n};\n\nconst URL_SCHEME_PATTERN = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:/;\nconst SAFE_DATA_IMAGE_URL_PATTERN = /^data:image\\//i;\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\nfunction normalizeDeviceType(deviceType: string | undefined): string {\n return (deviceType ?? '').toLowerCase().replace(/_/g, '-');\n}\n\nfunction isRelativeUrl(url: string): boolean {\n return !URL_SCHEME_PATTERN.test(url) && !url.startsWith('//');\n}\n\nfunction sanitizeDeviceImageUrl(url: string | undefined): string | undefined {\n if (!url) return undefined;\n const trimmed = url.trim();\n if (!trimmed) return undefined;\n\n if (isRelativeUrl(trimmed)) {\n return trimmed;\n }\n\n try {\n const parsedUrl = new URL(trimmed);\n const protocol = parsedUrl.protocol.toLowerCase();\n\n if (protocol === 'https:' || protocol === 'blob:') {\n return parsedUrl.href;\n }\n\n if (protocol === 'data:' && SAFE_DATA_IMAGE_URL_PATTERN.test(trimmed)) {\n return trimmed;\n }\n\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction toCssUrlValue(url: string): string {\n return `url(${JSON.stringify(url)})`;\n}\n\nfunction isPowerPort(port: Port): boolean {\n return isPowerPortType(port.type);\n}\n\nfunction resolvePowerConnectorType(port: Port, label: string): string {\n if (typeof port.connectorType === 'string' && port.connectorType.trim().length > 0) {\n return port.connectorType;\n }\n\n const normalizedType = String(port.type ?? '').toLowerCase();\n if (normalizedType.includes('c19') || normalizedType.includes('c20')) {\n return 'C19';\n }\n if (normalizedType.includes('c13') || normalizedType.includes('c14')) {\n return 'C13';\n }\n if (normalizedType.includes('power_ac')) {\n return 'AC';\n }\n\n return getDeviceConnectorType(label);\n}\n\nfunction getHandleId(portBlockName: string, port: Port): string {\n return buildPortHandleId(portBlockName, port);\n}\n\nfunction resolveCurrentFace(\n view: NetworkNode['data']['view'],\n ports: PortBlock[],\n rearPorts: PortBlock[],\n frontImageUrl?: string,\n rearImageUrl?: string\n): DeviceFace {\n const hasFront = ports.length > 0 || !!frontImageUrl;\n const hasRear = rearPorts.length > 0 || !!rearImageUrl;\n return view || (hasFront ? 'front' : hasRear ? 'rear' : 'front');\n}\n\nfunction resolveBackgroundSize(imageFit?: DeviceImageFit, stretchToFit?: boolean): React.CSSProperties['backgroundSize'] {\n if (stretchToFit === true || imageFit === 'fill') {\n return FILL_BACKGROUND_SIZE;\n }\n\n // `none` and `scale-down` are object-fit terms; map them to valid background-size values.\n if (imageFit === 'none') {\n return 'auto';\n }\n if (imageFit === 'scale-down') {\n return 'contain';\n }\n return imageFit ?? 'cover';\n}\n\nfunction getConnectedPortColor(port: Port): string {\n if (isPowerPort(port)) {\n return port.type === 'power_c19' ? '#fbbf24' : '#f59e0b';\n }\n if (port.type === 'console' || port.type === 'mgmt') {\n return '#8b5cf6';\n }\n if (port.type === 'usb') {\n return DEFAULT_CONNECTED_PORT_COLOR;\n }\n if (port.cableType) {\n return CONNECTED_CABLE_COLORS[port.cableType] ?? DEFAULT_CONNECTED_PORT_COLOR;\n }\n return DEFAULT_CONNECTED_PORT_COLOR;\n}\n\nfunction getPortColor(port: Port): string {\n if (!port.connected) {\n return DISCONNECTED_PORT_COLOR;\n }\n return getConnectedPortColor(port);\n}\n\nfunction getPortBlocksSignature(portBlocks: PortBlock[]): string {\n return portBlocks\n .map((block) => {\n const portsSignature = block.ports\n .map((port) => {\n const position = port.position\n ? [\n port.position.side ?? '',\n port.position.offsetPercent ?? '',\n port.position.offsetPx ?? '',\n port.position.xPercent ?? '',\n port.position.yPercent ?? '',\n ].join(':')\n : '';\n return [\n port.id ?? '',\n port.label,\n port.type ?? '',\n port.connected ? '1' : '0',\n port.cableType ?? '',\n port.connectorType ?? '',\n position,\n ].join(':');\n })\n .join(',');\n return `${block.name}[${portsSignature}]`;\n })\n .join('|');\n}\n\nfunction getBaseHandleStyle(\n portWidth: number,\n portHeight: number,\n portColor: string,\n borderColor: string,\n compactMinSize: boolean = false\n): React.CSSProperties {\n return {\n width: `${portWidth}px`,\n height: `${portHeight}px`,\n minWidth: compactMinSize ? `${portWidth}px` : undefined,\n minHeight: compactMinSize ? `${portHeight}px` : undefined,\n background: portColor,\n border: `0.5px solid ${borderColor}`,\n boxSizing: 'border-box',\n borderRadius: '1px',\n cursor: 'pointer',\n zIndex: 2,\n };\n}\n\nfunction getGenericPortDimensions(faceRegionWidth: number): { width: number; height: number } {\n // Keep non-power connector markers visually consistent across 1U/2U/4U devices.\n // Physical connector size does not scale with chassis height, so size by face width.\n // Make drag targets taller than they are wide so dense two-row switch faces remain legible.\n const width = Math.max(5, Math.min(7, Math.round(faceRegionWidth * 0.02)));\n const height = Math.max(8, Math.min(10, Math.round(width * 1.45)));\n return { width, height };\n}\n\nfunction clampPercent(value: number): number {\n return Math.max(0, Math.min(100, value));\n}\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction hasAbsolutePortCoordinates(port: Port): boolean {\n return typeof port.position?.xPercent === 'number' && typeof port.position?.yPercent === 'number';\n}\n\ninterface AbsolutePortLayoutEntry {\n handleId: string;\n xPercent: number;\n yPercent: number;\n side?: PortSide;\n}\n\nfunction resolveAbsolutePortLayoutHints(\n portBlocks: PortBlock[],\n faceRegionWidth: number,\n deviceHeight: number,\n defaultPortWidth: number,\n defaultPortHeight: number\n): { heightByHandleId: Map<string, number>; bottomAnchoredHandleIds: Set<string> } {\n const entries: AbsolutePortLayoutEntry[] = [];\n for (const block of portBlocks) {\n for (const port of block.ports) {\n if (!hasAbsolutePortCoordinates(port)) {\n continue;\n }\n entries.push({\n handleId: getHandleId(block.name, port),\n xPercent: clampPercent(port.position!.xPercent as number),\n yPercent: clampPercent(port.position!.yPercent as number),\n side: port.position?.side,\n });\n }\n }\n\n if (entries.length === 0) {\n return { heightByHandleId: new Map(), bottomAnchoredHandleIds: new Set() };\n }\n\n const bottomAnchoredHandleIds = new Set<string>();\n const uniqueRows = [...new Set(entries.map((entry) => Number(entry.yPercent.toFixed(2))))].sort((a, b) => a - b);\n if (uniqueRows.length >= 2) {\n const bottomRowY = uniqueRows[uniqueRows.length - 1];\n for (const entry of entries) {\n if (entry.side !== 'top') {\n continue;\n }\n if (Math.abs(entry.yPercent - bottomRowY) <= 0.15) {\n bottomAnchoredHandleIds.add(entry.handleId);\n }\n }\n }\n\n const heightByHandleId = new Map<string, number>();\n const xProximityPercent = Math.max(\n 1.75,\n (((defaultPortWidth + 1) / Math.max(faceRegionWidth, 1)) * 100) + 0.2\n );\n\n for (const entry of entries) {\n let minGapPercent = Number.POSITIVE_INFINITY;\n for (const candidate of entries) {\n if (candidate.handleId === entry.handleId) {\n continue;\n }\n const xGapPercent = Math.abs(candidate.xPercent - entry.xPercent);\n if (xGapPercent > xProximityPercent) {\n continue;\n }\n const yGapPercent = Math.abs(candidate.yPercent - entry.yPercent);\n if (yGapPercent <= 0) {\n continue;\n }\n minGapPercent = Math.min(minGapPercent, yGapPercent);\n }\n\n if (!Number.isFinite(minGapPercent)) {\n continue;\n }\n\n const minGapPx = (deviceHeight * minGapPercent) / 100;\n const compactHeight = Math.floor(minGapPx - 0.25);\n const resolvedHeight = clampNumber(compactHeight, 1, defaultPortHeight);\n if (resolvedHeight < defaultPortHeight) {\n heightByHandleId.set(entry.handleId, resolvedHeight);\n }\n }\n\n return { heightByHandleId, bottomAnchoredHandleIds };\n}\n\nfunction mapPortSideToPosition(side: PortSide): Position {\n switch (side) {\n case 'top':\n return Position.Top;\n case 'right':\n return Position.Right;\n case 'bottom':\n return Position.Bottom;\n case 'left':\n return Position.Left;\n default:\n return Position.Top;\n }\n}\n\nfunction inferSideFromAbsolutePercent(xPercent: number, yPercent: number): PortSide {\n const distances: Array<{ side: PortSide; distance: number }> = [\n { side: 'left', distance: xPercent },\n { side: 'right', distance: 100 - xPercent },\n { side: 'top', distance: yPercent },\n { side: 'bottom', distance: 100 - yPercent },\n ];\n distances.sort((a, b) => a.distance - b.distance);\n return distances[0].side;\n}\n\nfunction getCustomHandlePlacement(\n port: Port,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number,\n absoluteCenterYOverridePx?: number,\n absoluteSideOverride?: PortSide\n): HandlePlacement | undefined {\n if (!port.position) {\n return undefined;\n }\n\n const hasAbsoluteCoordinates =\n typeof port.position.xPercent === 'number' && typeof port.position.yPercent === 'number';\n if (hasAbsoluteCoordinates) {\n const xPercent = clampPercent(port.position.xPercent as number);\n const yPercent = clampPercent(port.position.yPercent as number);\n const side = absoluteSideOverride ?? port.position.side ?? inferSideFromAbsolutePercent(xPercent, yPercent);\n const minCenterX = (portWidth / 2) + DEVICE_FACE_BORDER_PX;\n const maxCenterX = Math.max(minCenterX, faceRegionWidth - (portWidth / 2));\n const minCenterY = (portHeight / 2) + DEVICE_FACE_BORDER_PX;\n const maxCenterY = Math.max(minCenterY, deviceHeight - (portHeight / 2));\n const centerX = clampNumber((faceRegionWidth * xPercent) / 100, minCenterX, maxCenterX);\n const centerY = clampNumber(\n absoluteCenterYOverridePx ?? (deviceHeight * yPercent) / 100,\n minCenterY,\n maxCenterY\n );\n return {\n position: mapPortSideToPosition(side),\n style: {\n left: `${centerX - portWidth / 2 - DEVICE_FACE_BORDER_PX}px`,\n top: `${centerY - portHeight / 2 - DEVICE_FACE_BORDER_PX}px`,\n right: 'initial',\n bottom: 'initial',\n transform: 'none',\n },\n };\n }\n\n if (!port.position.side) {\n return undefined;\n }\n\n const side = port.position.side;\n const offsetPercent =\n typeof port.position.offsetPercent === 'number'\n ? clampPercent(port.position.offsetPercent)\n : undefined;\n const offsetPx = typeof port.position.offsetPx === 'number' ? port.position.offsetPx : undefined;\n const minCenterX = portWidth / 2;\n const maxCenterX = Math.max(minCenterX, faceRegionWidth - portWidth / 2);\n const minCenterY = portHeight / 2;\n const maxCenterY = Math.max(minCenterY, deviceHeight - portHeight / 2);\n\n switch (side) {\n case 'top': {\n const rawCenterX = offsetPx !== undefined\n ? offsetPx\n : (faceRegionWidth * (offsetPercent ?? 50)) / 100;\n const centerX = clampNumber(rawCenterX, minCenterX, maxCenterX);\n return {\n position: Position.Top,\n style: {\n top: '0px',\n left: `${centerX}px`,\n right: undefined,\n bottom: undefined,\n transform: 'translate(-50%, 50%)',\n },\n };\n }\n case 'bottom': {\n const rawCenterX = offsetPx !== undefined\n ? offsetPx\n : (faceRegionWidth * (offsetPercent ?? 50)) / 100;\n const centerX = clampNumber(rawCenterX, minCenterX, maxCenterX);\n return {\n position: Position.Bottom,\n style: {\n bottom: '0px',\n left: `${centerX}px`,\n right: undefined,\n top: undefined,\n transform: 'translate(-50%, -50%)',\n },\n };\n }\n case 'left': {\n const rawCenterY = offsetPx !== undefined\n ? offsetPx\n : (deviceHeight * (offsetPercent ?? 50)) / 100;\n const centerY = clampNumber(rawCenterY, minCenterY, maxCenterY);\n return {\n position: Position.Left,\n style: {\n left: '0px',\n top: `${centerY}px`,\n right: undefined,\n bottom: undefined,\n transform: 'translate(50%, -50%)',\n },\n };\n }\n case 'right': {\n const rawCenterY = offsetPx !== undefined\n ? offsetPx\n : (deviceHeight * (offsetPercent ?? 50)) / 100;\n const centerY = clampNumber(rawCenterY, minCenterY, maxCenterY);\n return {\n position: Position.Right,\n style: {\n right: '0px',\n top: `${centerY}px`,\n left: undefined,\n bottom: undefined,\n transform: 'translate(-50%, -50%)',\n },\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction getDistributedRowCenterX(\n rowIndex: number,\n rowCount: number,\n portWidth: number,\n faceRegionWidth: number\n): number {\n const minCenterX = portWidth / 2;\n const maxCenterX = Math.max(minCenterX, faceRegionWidth - (portWidth / 2));\n return rowCount === 1\n ? (minCenterX + maxCenterX) / 2\n : minCenterX + (rowIndex * (maxCenterX - minCenterX)) / (rowCount - 1);\n}\n\nfunction getAlternatingTopBottomPlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n faceRegionWidth: number\n): HandlePlacement {\n const topRow = portIndex % 2 === 0;\n const topCount = Math.ceil(portCount / 2);\n const bottomCount = Math.floor(portCount / 2);\n const rowCount = Math.max(topRow ? topCount : bottomCount, 1);\n const rowIndex = topRow ? Math.floor(portIndex / 2) : Math.floor((portIndex - 1) / 2);\n const centerX = getDistributedRowCenterX(\n rowIndex,\n rowCount,\n portWidth,\n faceRegionWidth\n );\n\n if (topRow) {\n return {\n position: Position.Top,\n style: {\n transform: 'translateY(50%)',\n left: `${centerX - portWidth / 2}px`,\n },\n };\n }\n\n return {\n position: Position.Bottom,\n style: {\n transform: 'translateY(-50%)',\n left: `${centerX - portWidth / 2}px`,\n },\n };\n}\n\nfunction getAlternatingTopStackPlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number\n): HandlePlacement {\n const topRow = portIndex % 2 === 0;\n const topCount = Math.ceil(portCount / 2);\n const bottomCount = Math.floor(portCount / 2);\n const rowCount = Math.max(topRow ? topCount : bottomCount, 1);\n const rowIndex = topRow ? Math.floor(portIndex / 2) : Math.floor((portIndex - 1) / 2);\n const centerX = getDistributedRowCenterX(\n rowIndex,\n rowCount,\n portWidth,\n faceRegionWidth\n );\n\n const topPaddingPx = 1;\n const rowGapPx = clampNumber(Math.round(portHeight * 0.75), 1, 4);\n const maxTopPx = Math.max(topPaddingPx, deviceHeight - portHeight - 1);\n const secondRowTopPx = clampNumber(topPaddingPx + portHeight + rowGapPx, topPaddingPx, maxTopPx);\n const topPx = topRow ? topPaddingPx : secondRowTopPx;\n\n return {\n position: Position.Top,\n style: {\n transform: 'none',\n left: `${centerX - portWidth / 2}px`,\n top: `${topPx}px`,\n right: undefined,\n bottom: undefined,\n },\n };\n}\n\nfunction getFrontPowerHandlePlacement(\n port: Port,\n portIndex: number,\n portCount: number,\n deviceHeight: number,\n label: string\n): HandlePlacement {\n const connectorType = resolvePowerConnectorType(port, label);\n const powerStyle = getPowerPortStyle(connectorType);\n\n let topValue: string;\n if (deviceHeight <= 20) {\n const paddingPx = 2;\n const minTop = paddingPx;\n const maxTop = Math.max(minTop, deviceHeight - powerStyle.height - paddingPx);\n const topPx = portCount <= 1\n ? (minTop + maxTop) / 2\n : minTop + (portIndex * (maxTop - minTop)) / (portCount - 1);\n topValue = `${topPx}px`;\n } else {\n topValue = `${25 + (portIndex * 50)}%`;\n }\n\n return {\n position: Position.Right,\n style: {\n transform: 'translateX(-50%)',\n top: topValue,\n width: `${powerStyle.width}px`,\n height: `${powerStyle.height}px`,\n background: powerStyle.color,\n border: `1px solid ${powerStyle.borderColor}`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: powerStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: powerStyle.borderRadius,\n clipPath: powerStyle.clipPath,\n },\n };\n}\n\nfunction getFrontHandlePlacement(\n portIndex: number,\n portCount: number,\n portWidth: number,\n faceRegionWidth: number\n): HandlePlacement {\n if (portCount === 1) {\n const rightPadding = Math.max(6, Math.round(faceRegionWidth * 0.04));\n const leftPx = Math.max(portWidth / 2, faceRegionWidth - rightPadding - portWidth / 2);\n return {\n position: Position.Top,\n style: {\n transform: 'translateY(50%)',\n left: `${leftPx}px`,\n right: undefined,\n },\n };\n }\n\n return getAlternatingTopBottomPlacement(portIndex, portCount, portWidth, faceRegionWidth);\n}\n\nfunction getRearHandlePlacement(\n port: Port,\n portIndex: number,\n portCount: number,\n portWidth: number,\n portHeight: number,\n faceRegionWidth: number,\n deviceHeight: number,\n normalizedDeviceType: string,\n label: string\n): HandlePlacement {\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n const isSwitch = normalizedDeviceType === 'switch';\n if (isPatchPanel || isSwitch) {\n return getAlternatingTopBottomPlacement(portIndex, portCount, portWidth, faceRegionWidth);\n }\n\n if (isPowerPort(port)) {\n const connectorType = resolvePowerConnectorType(port, label);\n const powerStyle = getPowerPortStyle(connectorType);\n\n let topValue: string;\n if (deviceHeight <= 20) {\n // Keep 1U power handles inside the node even when connectors grow.\n const paddingPx = 2;\n const minTop = paddingPx;\n const maxTop = Math.max(minTop, deviceHeight - powerStyle.height - paddingPx);\n const topPx = portCount <= 1\n ? (minTop + maxTop) / 2\n : minTop + (portIndex * (maxTop - minTop)) / (portCount - 1);\n topValue = `${topPx}px`;\n } else {\n topValue = `${25 + (portIndex * 50)}%`;\n }\n\n return {\n position: Position.Left,\n style: {\n transform: 'translateX(50%)',\n top: topValue,\n width: `${powerStyle.width}px`,\n height: `${powerStyle.height}px`,\n background: powerStyle.color,\n border: `1px solid ${powerStyle.borderColor}`,\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: powerStyle.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: powerStyle.borderRadius,\n clipPath: powerStyle.clipPath,\n },\n };\n }\n\n return {\n position: Position.Right,\n style: {\n transform: 'translate(-50%, -50%)',\n top: `${\n clampNumber(\n portCount <= 1\n ? deviceHeight / 2\n : (portHeight / 2) + ((portIndex * Math.max(deviceHeight - portHeight, 0)) / Math.max(portCount - 1, 1)),\n portHeight / 2,\n Math.max(portHeight / 2, deviceHeight - portHeight / 2)\n )\n }px`,\n },\n };\n}\n\nfunction getHandleRoles(\n isPower: boolean,\n normalizedDeviceType: string,\n face: DeviceFace,\n isConnected: boolean\n): { primary: HandleRole; secondary?: HandleRole } {\n if (isPower) {\n return { primary: 'target' };\n }\n\n const isPatchPanel = normalizedDeviceType === 'patch-panel';\n if (normalizedDeviceType === 'switch' || normalizedDeviceType === 'router') {\n return { primary: 'source', secondary: 'target' };\n }\n if (isPatchPanel) {\n return face === 'rear'\n ? { primary: 'source', secondary: 'target' }\n : { primary: 'target', secondary: 'source' };\n }\n\n return { primary: isConnected ? 'source' : 'target' };\n}\n\n/**\n * Device visualization component with port management.\n * \n * Represents a device that can be placed in a rack. Supports port configuration,\n * U positioning, front/rear views, and various device types (servers, switches, routers, etc.).\n * \n * @example\n * ```tsx\n * {\n * id: 'server-1',\n * type: 'device',\n * position: { x: 120, y: 150 },\n * parentId: 'rack-1',\n * data: {\n * label: 'Web Server',\n * deviceType: 'server',\n * uPosition: 1,\n * ports: [{\n * name: 'Network Ports',\n * ports: [\n * { label: 'eth0', connected: true, type: 'ethernet' }\n * ]\n * }]\n * }\n * }\n * ```\n * \n * @public\n */\nexport const DeviceNode: React.FC<NodeProps<NetworkNode['data']>> = ({ id, data, selected }) => {\n const updateNodeInternals = useUpdateNodeInternals();\n const {\n label,\n status = 'active',\n deviceType = 'server',\n manufacturer,\n uHeight = 1,\n width = Width.FULL,\n ports: rawPorts,\n rearPorts: rawRearPorts,\n view,\n rackWidthPx,\n frontImageUrl,\n rearImageUrl,\n imageFit,\n imagePosition,\n imageRepeat,\n stretchToFit,\n } = data;\n const ports = React.useMemo<PortBlock[]>(\n () => (Array.isArray(rawPorts) ? rawPorts : []),\n [rawPorts]\n );\n const rearPorts = React.useMemo<PortBlock[]>(\n () => (Array.isArray(rawRearPorts) ? rawRearPorts : []),\n [rawRearPorts]\n );\n\n const normalizedDeviceType = normalizeDeviceType(deviceType);\n const effectiveRackWidth = rackWidthPx ?? RACK_WIDTH_PX;\n const splitFaceLayout = isSplitFaceRackLayout(data);\n const mountMode = getRackMountMode(data);\n const resolvedFace = resolveCurrentFace(view, ports, rearPorts, frontImageUrl, rearImageUrl);\n const visibleFaces = React.useMemo(\n () => splitFaceLayout ? getVisibleFacesForMountMode(mountMode) : [resolvedFace],\n [splitFaceLayout, mountMode, resolvedFace]\n );\n const currentFace = visibleFaces[0] ?? resolvedFace;\n const showSplitBothFaces = splitFaceLayout && mountMode === 'both';\n const deviceHeight = uHeight * U_HEIGHT_PX;\n const rackFaceGapPx = getRackFaceGapPx(data);\n const rightFaceOffsetPx = effectiveRackWidth + rackFaceGapPx;\n\n const handleLayoutSignature = React.useMemo(() => {\n return [\n splitFaceLayout ? 'split' : 'single',\n mountMode,\n visibleFaces.join(','),\n currentFace,\n normalizedDeviceType,\n label,\n deviceHeight.toString(),\n effectiveRackWidth.toString(),\n rightFaceOffsetPx.toString(),\n getPortBlocksSignature(ports),\n getPortBlocksSignature(rearPorts),\n ].join('|');\n }, [\n splitFaceLayout,\n mountMode,\n visibleFaces,\n currentFace,\n normalizedDeviceType,\n label,\n deviceHeight,\n effectiveRackWidth,\n rightFaceOffsetPx,\n ports,\n rearPorts,\n ]);\n\n useIsomorphicLayoutEffect(() => {\n updateNodeInternals(id);\n }, [handleLayoutSignature, id, updateNodeInternals]);\n\n const resolveFaceBackgroundStyle = React.useCallback((face: DeviceFace): React.CSSProperties => {\n const backgroundImageUrl = face === 'rear' ? rearImageUrl : frontImageUrl;\n const safeBackgroundImageUrl = sanitizeDeviceImageUrl(backgroundImageUrl);\n if (!safeBackgroundImageUrl) {\n return {};\n }\n\n return {\n backgroundImage: toCssUrlValue(safeBackgroundImageUrl),\n backgroundSize: resolveBackgroundSize(imageFit, stretchToFit),\n backgroundPosition: imagePosition ?? 'center',\n backgroundRepeat: imageRepeat ?? 'no-repeat',\n };\n }, [rearImageUrl, frontImageUrl, imageFit, stretchToFit, imagePosition, imageRepeat]);\n\n const frontBackgroundStyle = React.useMemo(\n () => resolveFaceBackgroundStyle('front'),\n [resolveFaceBackgroundStyle]\n );\n const rearBackgroundStyle = React.useMemo(\n () => resolveFaceBackgroundStyle('rear'),\n [resolveFaceBackgroundStyle]\n );\n const activeBackgroundStyle = currentFace === 'rear' ? rearBackgroundStyle : frontBackgroundStyle;\n\n let rackDeviceWidth: string;\n let rackDeviceLeft: string | undefined;\n if (splitFaceLayout) {\n const bodyWidth = getRackDeviceBodyWidthPx(data, data);\n rackDeviceWidth = `${bodyWidth + 4}px`;\n // In split-face racks, React Flow child node position already carries face offset.\n // Applying an internal left offset here would shift the device twice.\n rackDeviceLeft = undefined;\n } else {\n const fullWidthPx = effectiveRackWidth + 4;\n const halfWidthPx = Math.floor(effectiveRackWidth / 2);\n rackDeviceWidth = width === Width.HALF ? `${halfWidthPx}px` : `${fullWidthPx}px`;\n rackDeviceLeft = width === Width.HALF ? `${halfWidthPx}px` : undefined;\n }\n\n const isOneUServer = normalizedDeviceType === 'server' && uHeight === 1;\n const statusColor = getStatusColor(status);\n const deviceContainerStyle: DeviceNodeCssVars = {\n '--rn-device-bg-image': showSplitBothFaces ? 'none' : String(activeBackgroundStyle.backgroundImage ?? 'none'),\n '--rn-device-bg-position': String(activeBackgroundStyle.backgroundPosition ?? 'center'),\n '--rn-device-bg-repeat': String(activeBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n '--rn-device-bg-size': String(activeBackgroundStyle.backgroundSize ?? 'cover'),\n '--rn-device-border-color': statusColor,\n '--rn-device-box-shadow': selected ? '0 0 0 1px #3b82f6' : '0 1px 2px rgba(0,0,0,0.1)',\n '--rn-device-height': `${deviceHeight}px`,\n '--rn-device-left': rackDeviceLeft ?? 'auto',\n '--rn-device-status-color': statusColor,\n '--rn-device-translate-y': isOneUServer ? '-1px' : '0px',\n '--rn-device-width': rackDeviceWidth,\n };\n\n const frontHandleIds = React.useMemo(() => {\n const ids = new Set<string>();\n for (const block of ports) {\n for (const port of block.ports) {\n ids.add(getHandleId(block.name, port));\n }\n }\n return ids;\n }, [ports]);\n\n const resolveRenderedHandleId = React.useCallback((handleId: string, face: DeviceFace): string => {\n if (face === 'rear' && showSplitBothFaces && frontHandleIds.has(handleId)) {\n return `${handleId}--rear`;\n }\n return handleId;\n }, [frontHandleIds, showSplitBothFaces]);\n\n const renderPortsFromArray = React.useCallback((\n portBlocks: PortBlock[],\n face: DeviceFace,\n faceOffsetPx: number = 0,\n faceRegionWidth: number = effectiveRackWidth\n ) => {\n const handles: React.ReactElement[] = [];\n if (portBlocks.length === 0) {\n return handles;\n }\n\n // Keep non-power ports at a stable visual size across chassis heights.\n const { width: portWidth, height: portHeight } = getGenericPortDimensions(faceRegionWidth);\n const { heightByHandleId, bottomAnchoredHandleIds } = resolveAbsolutePortLayoutHints(\n portBlocks,\n faceRegionWidth,\n deviceHeight,\n portWidth,\n portHeight\n );\n const totalPortsOnFace = portBlocks.reduce((total, block) => total + block.ports.length, 0);\n const shouldLineUpDenseSwitchPortsAgainstTop =\n (normalizedDeviceType === 'switch' || normalizedDeviceType === 'patch-panel') &&\n totalPortsOnFace >= 24;\n const shouldAutoBottomAnchorAbsoluteRows =\n normalizedDeviceType === 'switch' || normalizedDeviceType === 'patch-panel';\n\n for (const portBlock of portBlocks) {\n for (let portIndex = 0; portIndex < portBlock.ports.length; portIndex += 1) {\n const port = portBlock.ports[portIndex];\n const handleId = getHandleId(portBlock.name, port);\n const isPower = isPowerPort(port);\n\n // Resolve actual port dimensions — power ports use connector-specific\n // sizes from getPowerPortStyle which differ from the generic dimensions.\n // Using the correct size here ensures clamp bounds and center-to-corner\n // offsets in getCustomHandlePlacement are accurate.\n let actualPortWidth = portWidth;\n let actualPortHeight = portHeight;\n if (isPower) {\n const connectorType = resolvePowerConnectorType(port, label);\n const powerStyle = getPowerPortStyle(connectorType);\n actualPortWidth = powerStyle.width;\n actualPortHeight = powerStyle.height;\n } else if (hasAbsolutePortCoordinates(port)) {\n const heightOverride = heightByHandleId.get(handleId);\n if (heightOverride !== undefined) {\n actualPortHeight = heightOverride;\n actualPortWidth = clampNumber(Math.round(actualPortHeight * 1.2), 3, portWidth);\n }\n }\n\n const portColor = getPortColor(port);\n const borderColor = port.connected ? portColor : DISCONNECTED_PORT_BORDER_COLOR;\n const useCompactMinSize = !isPower && hasAbsolutePortCoordinates(port) && actualPortHeight < portHeight;\n const baseStyle = getBaseHandleStyle(\n actualPortWidth,\n actualPortHeight,\n portColor,\n borderColor,\n useCompactMinSize\n );\n const defaultPlacement = face === 'front'\n ? (isPower\n ? getFrontPowerHandlePlacement(port, portIndex, portBlock.ports.length, deviceHeight, label)\n : shouldLineUpDenseSwitchPortsAgainstTop\n ? getAlternatingTopStackPlacement(\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight\n )\n : getFrontHandlePlacement(portIndex, portBlock.ports.length, portWidth, faceRegionWidth))\n : (\n !isPower && shouldLineUpDenseSwitchPortsAgainstTop\n ? getAlternatingTopStackPlacement(\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight\n )\n : getRearHandlePlacement(\n port,\n portIndex,\n portBlock.ports.length,\n portWidth,\n portHeight,\n faceRegionWidth,\n deviceHeight,\n normalizedDeviceType,\n label\n )\n );\n const customPlacement = getCustomHandlePlacement(\n port,\n actualPortWidth,\n actualPortHeight,\n faceRegionWidth,\n deviceHeight,\n undefined,\n shouldAutoBottomAnchorAbsoluteRows && bottomAnchoredHandleIds.has(handleId)\n ? 'bottom'\n : undefined\n );\n const placement = customPlacement\n ? (isPower\n ? {\n position: customPlacement.position,\n style: {\n ...defaultPlacement.style,\n ...customPlacement.style,\n },\n }\n : customPlacement)\n : defaultPlacement;\n\n const handleStyle = {\n ...baseStyle,\n ...placement.style,\n };\n const translatedHandleStyle: React.CSSProperties = { ...handleStyle };\n if (translatedHandleStyle.left !== undefined && faceOffsetPx !== 0) {\n if (typeof translatedHandleStyle.left === 'number') {\n translatedHandleStyle.left = `${translatedHandleStyle.left + faceOffsetPx}px`;\n } else {\n translatedHandleStyle.left = `calc(${translatedHandleStyle.left} + ${faceOffsetPx}px)`;\n }\n }\n\n if (showSplitBothFaces && translatedHandleStyle.left === undefined) {\n if (placement.position === Position.Left) {\n translatedHandleStyle.left = `${faceOffsetPx}px`;\n translatedHandleStyle.right = undefined;\n } else if (placement.position === Position.Right) {\n translatedHandleStyle.left = `${faceOffsetPx + faceRegionWidth}px`;\n translatedHandleStyle.right = undefined;\n }\n }\n\n const renderedHandleId = resolveRenderedHandleId(handleId, face);\n\n const roles = getHandleRoles(isPower, normalizedDeviceType, face, port.connected);\n if (roles.secondary) {\n const secondaryHandleStyle: React.CSSProperties =\n normalizedDeviceType === 'switch' || normalizedDeviceType === 'router'\n ? {\n ...translatedHandleStyle,\n background: 'transparent',\n border: 'none',\n opacity: 0,\n }\n : translatedHandleStyle;\n const secondaryTitle =\n normalizedDeviceType === 'switch' || normalizedDeviceType === 'router'\n ? `${portBlock.name} - ${port.label} (input) ${port.connected ? '(connected)' : '(disconnected)'}`\n : `${portBlock.name} - ${port.label} (${roles.secondary}) ${port.connected ? '(connected)' : '(disconnected)'}`;\n handles.push(\n <Handle\n key={`${renderedHandleId}-${roles.secondary}`}\n id={`${renderedHandleId}-${roles.secondary}`}\n type={roles.secondary}\n position={placement.position}\n style={secondaryHandleStyle}\n title={secondaryTitle}\n />\n );\n }\n\n handles.push(\n <Handle\n key={renderedHandleId}\n id={renderedHandleId}\n type={roles.primary}\n position={placement.position}\n style={translatedHandleStyle}\n title={`${portBlock.name} - ${port.label} ${port.connected ? '(connected)' : '(disconnected)'}`}\n >\n {isPower ? portIndex + 1 : undefined}\n </Handle>\n );\n }\n }\n\n return handles;\n }, [deviceHeight, effectiveRackWidth, label, normalizedDeviceType, resolveRenderedHandleId, showSplitBothFaces]);\n\n const renderedHandles = React.useMemo(() => {\n const handles: React.ReactElement[] = [];\n for (const face of visibleFaces) {\n if (face === 'front' && ports.length > 0) {\n const faceOffsetPx = showSplitBothFaces ? rightFaceOffsetPx : 0;\n handles.push(...renderPortsFromArray(ports, 'front', faceOffsetPx, effectiveRackWidth));\n }\n if (face === 'rear' && rearPorts.length > 0) {\n const faceOffsetPx = 0;\n handles.push(...renderPortsFromArray(rearPorts, 'rear', faceOffsetPx, effectiveRackWidth));\n }\n }\n return handles;\n }, [visibleFaces, ports, rearPorts, renderPortsFromArray, effectiveRackWidth, showSplitBothFaces, rightFaceOffsetPx]);\n\n return (\n <div\n className={`device-node ${selected ? 'selected' : ''} ${showSplitBothFaces ? 'device-node--split-both' : ''}`}\n style={deviceContainerStyle}\n >\n {showSplitBothFaces && (\n <div\n className=\"device-node__split-face-layer\"\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n pointerEvents: 'none',\n zIndex: 0,\n }}\n >\n <div\n className=\"device-node__split-face device-node__split-face--rear\"\n style={{\n width: `${effectiveRackWidth}px`,\n backgroundImage: String(rearBackgroundStyle.backgroundImage ?? 'none'),\n backgroundPosition: String(rearBackgroundStyle.backgroundPosition ?? 'center'),\n backgroundRepeat: String(rearBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n backgroundSize: String(rearBackgroundStyle.backgroundSize ?? 'cover'),\n }}\n />\n <div\n className=\"device-node__face-bridge\"\n data-testid=\"device-face-bridge\"\n style={{ width: `${rackFaceGapPx}px` }}\n >\n <div className=\"device-node__face-bridge-line\" />\n </div>\n <div\n className=\"device-node__split-face device-node__split-face--front\"\n style={{\n width: `${effectiveRackWidth}px`,\n backgroundImage: String(frontBackgroundStyle.backgroundImage ?? 'none'),\n backgroundPosition: String(frontBackgroundStyle.backgroundPosition ?? 'center'),\n backgroundRepeat: String(frontBackgroundStyle.backgroundRepeat ?? 'no-repeat'),\n backgroundSize: String(frontBackgroundStyle.backgroundSize ?? 'cover'),\n }}\n />\n </div>\n )}\n\n <div className=\"device-node__content\" style={{ position: 'relative', zIndex: 1 }}>\n <div className=\"device-node__label\">{label}</div>\n {uHeight > 1 && (\n <div className=\"device-node__manufacturer\">{manufacturer}</div>\n )}\n </div>\n\n {uHeight > 1 && (\n <div className=\"device-node__u-indicator\">{uHeight}U</div>\n )}\n\n <div className=\"device-node__status-indicator\" />\n\n {renderedHandles}\n </div>\n );\n};\n","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode, Port, PortBlock, PortPosition } from '../types';\nimport { getStatusColor } from '../utils/status-colors';\nimport { getPowerPortStyle, getPDUPortType } from '../utils/power-connectors';\nimport { buildPortHandleId } from '../utils/handle-ids';\n\nexport enum MgmtUnitPosition {\n TOP = 'top',\n MIDDLE = 'middle',\n BOTTOM = 'bottom'\n}\n\ninterface RenderablePDUPort {\n id: string;\n label: string;\n connectorType: 'C13' | 'C19' | 'AC';\n groupName: string;\n position?: PortPosition;\n}\n\ninterface PortRenderPlacement {\n position: Position;\n leftPx: number;\n topPx: number;\n}\n\nconst PDU_HEADER_HEIGHT = 20;\nconst PDU_BOTTOM_PADDING = 3;\nconst PDU_TOP_PADDING = 2;\nconst PDU_BORDER_WIDTH = 1;\nconst INTER_PORT_GAP_PX = 2;\nconst INTER_GROUP_GAP_PX = 6;\nconst MGMT_UNIT_HEIGHT_PX = 12;\n\nfunction clampPercent(value: number): number {\n return Math.max(0, Math.min(100, value));\n}\n\nfunction clampNumber(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction inferClosestSideFromPercent(xPercent: number, yPercent: number): NonNullable<PortPosition['side']> {\n const distances: Array<{ side: NonNullable<PortPosition['side']>; distance: number }> = [\n { side: 'left', distance: xPercent },\n { side: 'right', distance: 100 - xPercent },\n { side: 'top', distance: yPercent },\n { side: 'bottom', distance: 100 - yPercent },\n ];\n distances.sort((a, b) => a.distance - b.distance);\n return distances[0].side;\n}\n\nfunction normalizeConnectorType(value: unknown): 'C13' | 'C19' | 'AC' | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = value.trim().toUpperCase();\n if (normalized === 'C13') return 'C13';\n if (normalized === 'C19') return 'C19';\n if (normalized === 'AC') return 'AC';\n return undefined;\n}\n\nfunction resolvePortConnectorType(\n port: Port,\n fallback: 'C13' | 'C19' | 'AC'\n): 'C13' | 'C19' | 'AC' {\n const fromConnector = normalizeConnectorType(port.connectorType);\n if (fromConnector) {\n return fromConnector;\n }\n\n const type = String(port.type ?? '').toLowerCase();\n if (type.includes('c19')) return 'C19';\n if (type.includes('c13')) return 'C13';\n if (type.includes('power_ac')) return 'AC';\n return fallback;\n}\n\nfunction toPduPortGroups(data: NetworkNode['data']): PortBlock[] {\n if (Array.isArray(data.pduPortGroups) && data.pduPortGroups.length > 0) {\n return data.pduPortGroups;\n }\n if (Array.isArray(data.rearPorts) && data.rearPorts.length > 0) {\n return data.rearPorts;\n }\n if (Array.isArray(data.ports) && data.ports.length > 0) {\n return data.ports;\n }\n return [];\n}\n\nfunction getConnectorSequence(data: NetworkNode['data'], count: number): Array<'C13' | 'C19' | 'AC'> {\n if (!Array.isArray(data.portTypes) || data.portTypes.length === 0) {\n return Array.from({ length: count }, (_, index) => normalizeConnectorType(getPDUPortType(index)) ?? 'C13');\n }\n\n return Array.from({ length: count }, (_, index) => {\n const explicit = normalizeConnectorType(data.portTypes?.[index]);\n if (explicit) {\n return explicit;\n }\n return normalizeConnectorType(getPDUPortType(index)) ?? 'C13';\n });\n}\n\nfunction buildRenderablePorts(data: NetworkNode['data'], powerPorts: number): RenderablePDUPort[] {\n const customGroups = toPduPortGroups(data);\n const connectorSequence = getConnectorSequence(data, powerPorts);\n if (customGroups.length === 0) {\n return Array.from({ length: powerPorts }, (_, index) => ({\n id: `${index + 1}`,\n label: `${index + 1}`,\n connectorType: connectorSequence[index] ?? 'C13',\n groupName: 'Power',\n }));\n }\n\n const ports: RenderablePDUPort[] = [];\n let flatIndex = 0;\n customGroups.forEach((group) => {\n group.ports.forEach((port) => {\n const fallbackType = connectorSequence[flatIndex] ?? 'C13';\n ports.push({\n id: buildPortHandleId(group.name, port),\n label: port.label,\n connectorType: resolvePortConnectorType(port, fallbackType),\n groupName: group.name,\n position: port.position,\n });\n flatIndex += 1;\n });\n });\n return ports;\n}\n\nfunction getPortRenderHeightPx(port: RenderablePDUPort, index: number, mgmtPortIndex: number): number {\n if (index === mgmtPortIndex) {\n return MGMT_UNIT_HEIGHT_PX;\n }\n return getPowerPortStyle(port.connectorType).height;\n}\n\nfunction getRequiredBodyHeightPx(ports: RenderablePDUPort[], mgmtPortIndex: number): number {\n if (ports.length === 0) {\n return Math.max(PDU_TOP_PADDING + PDU_BOTTOM_PADDING + 1, 1);\n }\n\n let stackHeight = 0;\n for (let index = 0; index < ports.length; index += 1) {\n stackHeight += getPortRenderHeightPx(ports[index], index, mgmtPortIndex);\n if (index < ports.length - 1) {\n stackHeight += ports[index].groupName === ports[index + 1].groupName\n ? INTER_PORT_GAP_PX\n : INTER_GROUP_GAP_PX;\n }\n }\n\n return PDU_TOP_PADDING + stackHeight + PDU_BOTTOM_PADDING;\n}\n\nfunction buildAutoYPositions(ports: RenderablePDUPort[], bodyHeight: number, mgmtPortIndex: number): number[] {\n if (ports.length === 0) {\n return [];\n }\n\n const portHeights = ports.map((port, index) => getPortRenderHeightPx(port, index, mgmtPortIndex));\n const baseGaps: number[] = [];\n for (let index = 0; index < ports.length - 1; index += 1) {\n baseGaps.push(ports[index].groupName === ports[index + 1].groupName ? INTER_PORT_GAP_PX : INTER_GROUP_GAP_PX);\n }\n const totalPortHeights = portHeights.reduce((total, height) => total + height, 0);\n const totalBaseGaps = baseGaps.reduce((total, gap) => total + gap, 0);\n const requiredStackHeight = totalPortHeights + totalBaseGaps;\n const drawableHeight = Math.max(bodyHeight - PDU_TOP_PADDING - PDU_BOTTOM_PADDING, 1);\n\n let startOffset = 0;\n let adjustedGaps = baseGaps;\n const extraHeight = Math.max(0, drawableHeight - requiredStackHeight);\n if (extraHeight > 0) {\n if (baseGaps.length === 0) {\n startOffset = extraHeight / 2;\n } else {\n const weights = baseGaps.map((gap) => (gap === INTER_GROUP_GAP_PX ? 1.2 : 1));\n const totalWeight = weights.reduce((total, weight) => total + weight, 0);\n adjustedGaps = baseGaps.map((gap, index) => {\n if (totalWeight <= 0) {\n return gap;\n }\n return gap + (extraHeight * weights[index]) / totalWeight;\n });\n }\n }\n\n const centers: number[] = [];\n let cursor = PDU_TOP_PADDING + startOffset;\n for (let index = 0; index < portHeights.length; index += 1) {\n const height = portHeights[index];\n centers.push(cursor + height / 2);\n cursor += height;\n if (index < portHeights.length - 1) {\n cursor += adjustedGaps[index] ?? INTER_PORT_GAP_PX;\n }\n }\n return centers;\n}\n\nfunction resolveCustomPlacement(\n position: PortPosition | undefined,\n fallbackCenterY: number,\n bodyHeight: number,\n widthPx: number,\n handleWidth: number,\n handleHeight: number\n): PortRenderPlacement {\n if (!position) {\n return {\n position: Position.Right,\n leftPx: Math.round((widthPx - handleWidth) / 2) - 1,\n topPx: fallbackCenterY - (handleHeight / 2),\n };\n }\n\n const side = position.side;\n const sourcePosition =\n side === 'left'\n ? Position.Left\n : side === 'top'\n ? Position.Top\n : side === 'bottom'\n ? Position.Bottom\n : Position.Right;\n\n const offsetPercent = typeof position.offsetPercent === 'number' ? clampPercent(position.offsetPercent) : undefined;\n const offsetPx = typeof position.offsetPx === 'number' ? position.offsetPx : undefined;\n const xPercent = typeof position.xPercent === 'number' ? clampPercent(position.xPercent) : undefined;\n const yPercent = typeof position.yPercent === 'number' ? clampPercent(position.yPercent) : undefined;\n\n if (xPercent !== undefined && yPercent !== undefined) {\n const resolvedSide = side ?? inferClosestSideFromPercent(xPercent, yPercent);\n const resolvedPosition =\n resolvedSide === 'left'\n ? Position.Left\n : resolvedSide === 'top'\n ? Position.Top\n : resolvedSide === 'bottom'\n ? Position.Bottom\n : Position.Right;\n const drawableHeight = Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1);\n const centerX = (widthPx * xPercent) / 100;\n const centerY = clampNumber(\n (drawableHeight * yPercent) / 100,\n handleHeight / 2,\n Math.max(handleHeight / 2, bodyHeight - handleHeight / 2)\n );\n\n return {\n position: resolvedPosition,\n leftPx: centerX - (handleWidth / 2),\n topPx: centerY - (handleHeight / 2),\n };\n }\n\n let centerX = xPercent !== undefined ? (widthPx * xPercent) / 100 : widthPx - (handleWidth / 2) - 1;\n let centerY =\n yPercent !== undefined\n ? ((Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1) * yPercent) / 100)\n : fallbackCenterY;\n\n if (side === 'top' || side === 'bottom') {\n if (offsetPx !== undefined) {\n centerX = offsetPx;\n } else if (offsetPercent !== undefined) {\n centerX = (widthPx * offsetPercent) / 100;\n }\n centerY = side === 'top'\n ? (handleHeight / 2)\n : bodyHeight - (handleHeight / 2);\n } else {\n if (offsetPx !== undefined) {\n centerY = offsetPx;\n } else if (offsetPercent !== undefined) {\n centerY = ((Math.max(bodyHeight - PDU_BOTTOM_PADDING, 1) * offsetPercent) / 100);\n }\n if (side === 'left') {\n centerX = handleWidth / 2;\n } else if (side === 'right') {\n centerX = widthPx - (handleWidth / 2) - 1;\n }\n }\n\n centerY = clampNumber(\n centerY,\n handleHeight / 2,\n Math.max(handleHeight / 2, bodyHeight - handleHeight / 2)\n );\n\n return {\n position: sourcePosition,\n leftPx: centerX - (handleWidth / 2),\n topPx: centerY - (handleHeight / 2),\n };\n}\n\nfunction getMgmtPortIndex(mgmtUnit: NetworkNode['data']['mgmt_unit'], totalPorts: number): number {\n if (!mgmtUnit || totalPorts <= 0) {\n return -1;\n }\n if (mgmtUnit === MgmtUnitPosition.TOP) {\n return 0;\n }\n if (mgmtUnit === MgmtUnitPosition.BOTTOM) {\n return totalPorts - 1;\n }\n return Math.floor(totalPorts / 2);\n}\n\nfunction renderMgmtUnit(yCenter: number, widthPx: number): React.ReactElement {\n const mgmtWidth = 16;\n const mgmtHeight = 12;\n return (\n <div\n key=\"mgmt-unit\"\n style={{\n position: 'absolute',\n left: `${(widthPx - mgmtWidth) / 2}px`,\n top: `${yCenter - (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 <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 <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\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,\n widthPx = 15,\n mgmt_unit,\n } = data;\n\n const safePowerPorts = Math.max(0, powerPorts);\n const ports = buildRenderablePorts(data, safePowerPorts);\n const mgmtPortIndex = getMgmtPortIndex(mgmt_unit, ports.length);\n const requestedHeightPx = heightCm * 4.2;\n const minimumBodyHeightPx = getRequiredBodyHeightPx(ports, mgmtPortIndex);\n const bodyHeight = Math.max(requestedHeightPx - PDU_HEADER_HEIGHT, minimumBodyHeightPx);\n const bodyWidth = Math.max(widthPx - (PDU_BORDER_WIDTH * 2), 1);\n const heightPx = PDU_HEADER_HEIGHT + bodyHeight;\n const autoYPositions = buildAutoYPositions(ports, bodyHeight, mgmtPortIndex);\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 boxSizing: 'border-box',\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\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: `${PDU_HEADER_HEIGHT}px`,\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 <div\n style={{\n flex: 1,\n background: 'linear-gradient(180deg, #2d3748 0%, #1a202c 50%, #2d3748 100%)',\n position: 'relative',\n minHeight: `${heightPx - PDU_HEADER_HEIGHT}px`,\n overflow: 'hidden',\n }}\n >\n {ports.map((port, index) => {\n const fallbackCenterY = autoYPositions[index] ?? (bodyHeight / 2);\n if (mgmtPortIndex === index) {\n return renderMgmtUnit(fallbackCenterY, bodyWidth);\n }\n\n const style = getPowerPortStyle(port.connectorType);\n const placement = resolveCustomPlacement(\n port.position,\n fallbackCenterY,\n bodyHeight,\n bodyWidth,\n style.width,\n style.height\n );\n\n return (\n <Handle\n key={`handle-${port.id}`}\n type=\"source\"\n position={placement.position}\n id={port.id}\n style={{\n position: 'absolute',\n left: `${placement.leftPx}px`,\n top: `${placement.topPx}px`,\n right: 'initial',\n bottom: 'initial',\n width: `${style.width}px`,\n height: `${style.height}px`,\n background: style.color,\n border: `1px solid ${style.borderColor}`,\n boxSizing: 'border-box',\n transform: 'none',\n cursor: 'pointer',\n zIndex: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: style.fontSize,\n color: '#1a1a1a',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n borderRadius: style.borderRadius,\n clipPath: style.clipPath,\n }}\n title={`${port.groupName} - ${port.label} (${port.connectorType})`}\n >\n {port.label}\n </Handle>\n );\n })}\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 { getFiberPaint, 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 \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 const connectedIsRibbon =\n !!connectedEdge &&\n (connectedEdge.data?.isRibbon ||\n (connectedEdge.data?.ribbonFiberIds && Array.isArray(connectedEdge.data.ribbonFiberIds)));\n\n const edgeColor = connectedEdge?.data?.color;\n const edgeStriped =\n typeof connectedEdge?.data?.striped === 'boolean' ? connectedEdge.data.striped : undefined;\n\n let fiberPaint = getFiberPaint(fiberIdx);\n if (isRibbonTube || connectedIsRibbon) {\n fiberPaint = getFiberPaint(fiberIdx, { base: '#808080', striped: false });\n } else if (edgeColor || edgeStriped !== undefined) {\n fiberPaint = getFiberPaint(fiberIdx, {\n ...(edgeColor ? { base: edgeColor } : {}),\n ...(edgeStriped !== undefined ? { striped: edgeStriped } : {}),\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': fiberPaint.base,\n backgroundColor: fiberPaint.base,\n };\n \n if (fiberPaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberPaint.backgroundImage;\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={fiberPaint.base}\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={fiberPaint.base}\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","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getFiberPaint, 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 fiberPaint = getFiberPaint(fiberIdx);\n const baseColor = fiberPaint.base;\n\n const left = padding + (i * (handleSize + handleSpacing));\n const top = -(handleSize / 2);\n\n const handleBackground = fiberPaint.backgroundImage ? fiberPaint.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 (fiberPaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = fiberPaint.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","import React from 'react';\nimport { Handle, Position, NodeProps } from 'reactflow';\nimport { NetworkNode } from '../types';\nimport { getFiberPaint, 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 tubePaint = getFiberPaint(tubeIdx);\n const baseColor = tubePaint.base;\n\n const left = padding + (i * (handleWidth + handleSpacing));\n const top = -(handleHeight / 2);\n\n const handleBackground = tubePaint.backgroundImage ? tubePaint.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 (tubePaint.backgroundImage) {\n handleStyle['--fiber-bg-image'] = tubePaint.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","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 { HANDLE_EXTENSION_PX } from './constants';\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 * \n * @param node - The coupler node with optional couplerFiberCount in data\n * @returns Object with width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const node = { type: 'coupler', data: { couplerFiberCount: 2 } };\n * const dims = getCouplerDimensions(node);\n * // Returns: { width: 80, height: 30 }\n * ```\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 * \n * @param node - The tube node with optional fibersPerTube in data (default: 12)\n * @returns Object with width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const node = { type: 'tube', data: { fibersPerTube: 12 } };\n * const dims = getTubeDimensions(node);\n * // Returns: { width: calculated, height: 20 }\n * ```\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 * \n * Tray dimensions are fixed and do not depend on node data.\n * \n * @param _node - The tray node (unused, dimensions are fixed)\n * @returns Object with fixed width (TRAY_WIDTH_PX) and height (0)\n * @public\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 the maximum right edge (x + width) of child nodes\n * @param childNodes - Array of child nodes to check\n * @returns Maximum right edge position in pixels\n */\nfunction calculateMaxChildRight(childNodes: NetworkNode[]): number {\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 return maxRight;\n}\n\n/**\n * Calculate the maximum bottom edge (y + height) of child nodes\n * @param childNodes - Array of child nodes to check\n * @param startY - Starting Y position (e.g., header height)\n * @returns Maximum bottom edge position in pixels\n */\nfunction calculateMaxChildBottom(childNodes: NetworkNode[], startY: number = 0): number {\n let maxBottom = startY;\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 return maxBottom;\n}\n\n/**\n * Calculate panel width based on content\n * \n * @param panelNode - The panel node with optional panelWidth in data\n * @returns Panel width in pixels, or default PANEL_WIDTH_PX if not specified\n * @public\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 * \n * @param panelNode - The panel node with optional panelHeight in data\n * @returns Panel height in pixels, or default PANEL_HEIGHT_PX if not specified\n * @public\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 * \n * Calculates the usable width inside a panel after accounting for borders and padding.\n * \n * @param panelNode - The panel node\n * @returns Inner content width in pixels\n * @public\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 * \n * Calculates the X position for the right edge of a coupler within a panel.\n * \n * @param panelNode - The panel node containing the coupler\n * @param couplerWidth - Width of the coupler in pixels\n * @returns X position for the right edge of the coupler\n * @public\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 * \n * Converts a Y pixel coordinate to a slot number (1-indexed).\n * \n * @param y - Y coordinate in pixels\n * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)\n * @returns Slot position (1-indexed)\n * @public\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 * \n * Converts a slot number (1-indexed) to a Y pixel coordinate.\n * \n * @param slot - Slot position (1-indexed)\n * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)\n * @returns Y coordinate in pixels\n * @public\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 * \n * Snaps a coupler's position to the nearest valid slot within a panel.\n * \n * @param coupler - The coupler node to snap\n * @param panel - The panel node containing the coupler\n * @param position - Current position { x, y }\n * @returns Snapped position with optional slotPosition\n * @public\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 * \n * Automatically calculates the width and height of a panel based on its child nodes.\n * Supports special layouts for patch panels with tubes, trays, and couplers.\n * \n * @param panelNode - The panel node\n * @param childNodes - Array of child nodes within the panel\n * @returns Object with calculated width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const panel = { id: 'panel-1', type: 'patch-panel', data: {} };\n * const children = [tubeNode, trayNode, couplerNode];\n * const dims = calculatePanelDimensions(panel, children);\n * ```\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 \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 + HANDLE_EXTENSION_PX;\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 const maxRight = calculateMaxChildRight(childNodes);\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 const maxBottom = calculateMaxChildBottom(childNodes, PANEL_HEADER_HEIGHT);\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 * \n * Calculates the vertical spacing needed between couplers to fit them evenly\n * within the available height.\n * \n * @param numCouplers - Number of couplers to space\n * @param couplerHeight - Height of each coupler in pixels\n * @param availableHeight - Total available height in pixels\n * @returns Spacing between couplers in pixels (includes coupler height)\n * @public\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 * \n * Alias for calculateCouplerSpacing. Calculates spacing between coupler slots.\n * \n * @param numCouplers - Number of couplers to space\n * @param couplerHeight - Height of each coupler in pixels\n * @param availableHeight - Total available height in pixels\n * @returns Spacing between coupler slots in pixels\n * @public\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 * \n * Automatically calculates the width and height of a closure based on its child nodes.\n * Supports special layouts for closures with tubes and trays.\n * Closure layout: [padding] [left tubes] [spacing] [trays] [spacing] [right tubes] [padding]\n * \n * @param closureNode - The closure node\n * @param childNodes - Array of child nodes within the closure\n * @returns Object with calculated width and height in pixels\n * @public\n * \n * @example\n * ```ts\n * const closure = { id: 'closure-1', type: 'closure', data: {} };\n * const children = [leftTubeNode, trayNode, rightTubeNode];\n * const dims = calculateClosureDimensions(closure, children);\n * ```\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 \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 + HANDLE_EXTENSION_PX;\n } else {\n // Fallback: calculate based on rightmost child\n const maxRight = calculateMaxChildRight(childNodes);\n width = maxRight + PANEL_PADDING + HANDLE_EXTENSION_PX;\n }\n } else {\n // Standard layout: calculate based on rightmost child\n const maxRight = calculateMaxChildRight(childNodes);\n \n // Add padding and handle extension space\n width = maxRight + PANEL_PADDING + HANDLE_EXTENSION_PX;\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 const maxBottom = calculateMaxChildBottom(childNodes, PANEL_HEADER_HEIGHT);\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';\nimport { normalizeDirectionalHandleId } from './handle-ids';\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 normalizeDirectionalHandleId(handle);\n }\n return normalizeDirectionalHandleId(handle);\n};\n","import type { NetworkNode } from '../types';\nimport {\n buildPortHandleId,\n isPowerPortType,\n looksLikePowerHandleId,\n normalizeDirectionalHandleId,\n} from './handle-ids';\n\nexport type EndpointConnectionKind = 'power' | 'network' | 'unknown';\n\n/**\n * Classify a handle on a node as power, network, or unknown.\n * Used for validation and connection handling.\n */\nexport function getEndpointConnectionKind(\n node?: NetworkNode,\n handle?: string | null\n): EndpointConnectionKind {\n if (!node || !handle) {\n return 'unknown';\n }\n\n const normalizedHandle = normalizeDirectionalHandleId(handle);\n if (!normalizedHandle) {\n return 'unknown';\n }\n\n if (node.type === 'vertical-pdu') {\n return 'power';\n }\n\n const data = node.data ?? {};\n const frontBlocks = Array.isArray(\n (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports\n )\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray(\n (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts\n )\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts!\n : [];\n\n for (const block of [...frontBlocks, ...rearBlocks]) {\n for (const port of block.ports || []) {\n const expectedHandle = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\n if (expectedHandle === normalizedHandle) {\n return isPowerPortType(port.type) ? 'power' : 'network';\n }\n }\n }\n\n if (looksLikePowerHandleId(normalizedHandle) || /^\\d+$/.test(normalizedHandle)) {\n return 'power';\n }\n\n const handleLc = normalizedHandle.toLowerCase();\n const isStandardNetworkHandle =\n handleLc.startsWith('net-') ||\n handleLc.startsWith('port-') ||\n handleLc.startsWith('uplink-') ||\n handleLc.includes('fiber') ||\n handleLc.includes('ports');\n const isCustomPortName =\n /^[A-Z0-9]+-\\d+$/i.test(normalizedHandle) &&\n !handleLc.startsWith('pwr') &&\n !handleLc.startsWith('power');\n\n if (isStandardNetworkHandle || isCustomPortName) {\n return 'network';\n }\n\n return 'unknown';\n}\n\n/**\n * Returns true when the handle on the node is a power endpoint.\n * Used for power connection handling and edge replacement.\n */\nexport function isPowerEndpointHandle(\n node?: NetworkNode,\n handle?: string | null\n): boolean {\n return getEndpointConnectionKind(node, handle) === 'power';\n}\n","import type { NetworkEdge, NetworkNode } from '../types';\nimport { isFiberConnection, normalizeHandle } from '../utils/connection-rules';\nimport { getEndpointConnectionKind } from '../utils/endpoint-kind';\nimport {\n buildPortHandleId,\n isPowerPortType,\n looksLikePowerHandleId,\n normalizeDirectionalHandleId,\n} from '../utils/handle-ids';\nimport {\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\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 /** Optional edge id to ignore during occupancy checks (used for reconnect). */\n ignoreEdgeId?: string;\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 const fiberConnection = isFiberConnection(sourceNode, targetNode);\n\n if (!fiberConnection) {\n const sourceKind = getEndpointConnectionKind(sourceNode, params.sourceHandle);\n const targetKind = getEndpointConnectionKind(targetNode, params.targetHandle);\n\n if (sourceKind !== 'unknown' && targetKind !== 'unknown' && sourceKind !== targetKind) {\n return { valid: false, reason: `Cannot connect ${sourceKind} handle to ${targetKind} handle` };\n }\n\n const isPowerConnection = sourceKind === 'power' && targetKind === 'power';\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n if (isPowerConnection && !hasPduEndpoint) {\n return { valid: false, reason: 'Power connections must include a PDU endpoint' };\n }\n }\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 (params.ignoreEdgeId && e.id === params.ignoreEdgeId) {\n return false;\n }\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 (params.ignoreEdgeId && e.id === params.ignoreEdgeId) {\n return false;\n }\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 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 const rearHandleAliasSuffix = '--rear';\n let normalizedHandleId = normalizeDirectionalHandleId(handleId);\n const hasExplicitRearAlias = normalizedHandleId.endsWith(rearHandleAliasSuffix);\n if (hasExplicitRearAlias) {\n normalizedHandleId = normalizedHandleId.slice(0, -rearHandleAliasSuffix.length);\n }\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 // Split-face rear aliases are explicit and should take precedence over block inference.\n if (hasExplicitRearAlias) {\n return 'rear';\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<{ id?: string; label: string; type?: string }> }> }).ports)\n ? (data as { ports?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).ports!\n : [];\n const rearBlocks = Array.isArray((data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts)\n ? (data as { rearPorts?: Array<{ name: string; ports?: Array<{ id?: string; label: string; type?: string }> }> }).rearPorts!\n : [];\n\n // If the handleId matches a power label, treat as rear by default\n if (looksLikePowerHandleId(normalizedHandleId)) 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 expected = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\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 expected = buildPortHandleId(block.name, {\n id: port.id,\n label: port.label,\n type: isPowerPortType(port.type) ? port.type : undefined,\n });\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 getNodeParentId = (node: NetworkNode): string | undefined => {\n if (typeof node.parentId === 'string') {\n return node.parentId;\n }\n const legacyParent = (node as NetworkNode & { parentNode?: string }).parentNode;\n if (typeof legacyParent === 'string') {\n return legacyParent;\n }\n return undefined;\n };\n\n const getVisibleFaces = (node: NetworkNode): ViewFace[] => {\n const parentId = getNodeParentId(node);\n const parentRack = parentId ? state.nodes.find((n) => n.id === parentId && n.type === 'rack') : undefined;\n if (parentRack && isSplitFaceRackLayout(parentRack.data)) {\n return getVisibleFacesForMountMode(getRackMountMode(node.data));\n }\n\n const hasRearPorts = Array.isArray(node.data?.rearPorts) && node.data.rearPorts.length > 0;\n const hasFrontPorts = Array.isArray(node.data?.ports) && node.data.ports.length > 0;\n const deviceView: ViewFace = (node.data?.view as ViewFace) || (hasRearPorts && !hasFrontPorts ? 'rear' : 'front');\n return [deviceView];\n };\n\n const resolveEndpointVisibility = (nodeId: string, handle: string | null | undefined): number | undefined => {\n const node = state.nodes.find((n) => n.id === nodeId);\n const isRackDeviceNode =\n !!node &&\n (node.type === 'device' || node.type === 'server' || node.type === 'switch' || node.type === 'router');\n if (!isRackDeviceNode || !node) {\n return undefined;\n }\n\n const normalizedDeviceType = node.data?.deviceType?.toLowerCase().replace(/_/g, '-');\n if (normalizedDeviceType === 'patch-panel') {\n return undefined;\n }\n\n const visibleFaces = getVisibleFaces(node);\n const side = getHandleSide(handle || '', node);\n if (side) {\n return visibleFaces.includes(side) ? 1000 : 500;\n }\n\n const normalizedHandle = (handle || '').toString().replace(/-(source|target)$/i, '');\n const handleLc = normalizedHandle.toLowerCase();\n const isPowerHandle = handleLc.startsWith('pwr') || handleLc.startsWith('power');\n const isStandardNetworkHandle =\n handleLc.startsWith('net-') ||\n handleLc.startsWith('port-') ||\n handleLc.startsWith('uplink-') ||\n handleLc.includes('fiber') ||\n handleLc.includes('ports');\n const isCustomPortName =\n /^[A-Z0-9]+-\\d+$/i.test(normalizedHandle) &&\n !handleLc.startsWith('pwr') &&\n !handleLc.startsWith('power');\n const isNetworkHandle = isStandardNetworkHandle || isCustomPortName;\n\n if (isPowerHandle) {\n return visibleFaces.includes('rear') ? 1000 : 500;\n }\n if (isNetworkHandle) {\n return visibleFaces.includes('front') ? 1000 : 500;\n }\n\n return undefined;\n };\n\n const targetVisibility = resolveEndpointVisibility(edge.target, edge.targetHandle);\n if (targetVisibility !== undefined) {\n return targetVisibility;\n }\n\n const sourceVisibility = resolveEndpointVisibility(edge.source, edge.sourceHandle);\n if (sourceVisibility !== undefined) {\n return sourceVisibility;\n }\n\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","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((_state: NetworkDiagramState) => cb());\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((_state: NetworkDiagramState) => cb());\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((_state: NetworkDiagramState) => cb());\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","import { NetworkNode } from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from './constants';\nimport { getRackTotalWidthPx } from './rack-layout';\n\n/**\n * Calculate the bounding box of a rack node (header + body)\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 // Split-face layout doubles the width and includes the inter-face gap.\n const rackWidth = getRackTotalWidthPx(rack.data);\n const rackHeight = RACK_HEADER_HEIGHT + (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","import { Connection, Edge, addEdge } from 'reactflow';\nimport { NetworkEdge } from '../types';\nimport { normalizeDirectionalHandleId } from './handle-ids';\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 /** Which end of the connection to use (source or target) for finding the edge */\n findBy: 'source' | 'target';\n /** Which end of the existing edge to match against. Defaults to findBy. Use 'source' when the connection's target handle is on the edge's source (e.g. replacing switch connection when dragging from server to switch) */\n matchOn?: '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, matchOn = findBy, data } = options;\n\n // Determine which handle to search by from the connection\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 const normalizedHandle = normalizeDirectionalHandleId(handleId);\n\n // Find existing edge - use normalized handle comparison for bidirectional handles (e.g. Network-1-target)\n const existingEdge = edges.find(e => {\n if (matchOn === 'source') {\n return e.source === nodeId && normalizeDirectionalHandleId(e.sourceHandle) === normalizedHandle;\n } else {\n return e.target === nodeId && normalizeDirectionalHandleId(e.targetHandle) === normalizedHandle;\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 type { NetworkNode, RackMountMode } from '../types';\n\ntype MountResolutionNodeData = Pick<\n NetworkNode['data'],\n 'mountMode' | 'ports' | 'rearPorts' | 'frontImageUrl' | 'rearImageUrl' | 'view'\n>;\n\nfunction countPorts(\n portBlocks: MountResolutionNodeData['ports'] | MountResolutionNodeData['rearPorts']\n): number {\n if (!Array.isArray(portBlocks)) {\n return 0;\n }\n\n return portBlocks.reduce((total, block) => {\n return total + (Array.isArray(block.ports) ? block.ports.length : 0);\n }, 0);\n}\n\nfunction hasImage(url: string | undefined): boolean {\n return typeof url === 'string' && url.trim().length > 0;\n}\n\nexport function inferRackMountModeFromFaces(\n nodeData: Pick<MountResolutionNodeData, 'ports' | 'rearPorts' | 'frontImageUrl' | 'rearImageUrl'>\n): RackMountMode | undefined {\n const hasFront = countPorts(nodeData.ports) > 0 || hasImage(nodeData.frontImageUrl);\n const hasRear = countPorts(nodeData.rearPorts) > 0 || hasImage(nodeData.rearImageUrl);\n\n if (hasFront && hasRear) {\n return 'both';\n }\n if (hasFront) {\n return 'front';\n }\n if (hasRear) {\n return 'rear';\n }\n\n return undefined;\n}\n\nexport function resolveSplitRackMountModeForDrop(\n nodeData: MountResolutionNodeData,\n dropRelativeX: number,\n rackWidthPx: number,\n rackFaceGapPx: number\n): RackMountMode {\n const explicitMountMode = nodeData.mountMode;\n if (\n explicitMountMode === 'front' ||\n explicitMountMode === 'rear' ||\n explicitMountMode === 'both'\n ) {\n return explicitMountMode;\n }\n\n const inferredMountMode = inferRackMountModeFromFaces(nodeData);\n if (inferredMountMode) {\n return inferredMountMode;\n }\n\n if (nodeData.view === 'front' || nodeData.view === 'rear') {\n return nodeData.view;\n }\n\n const splitMidpointX = rackWidthPx + rackFaceGapPx / 2;\n return dropRelativeX >= splitMidpointX ? 'front' : 'rear';\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 applyEdgeChanges,\n applyNodeChanges,\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 {\n NetworkDiagramProps,\n NetworkNode,\n NetworkEdge,\n NetworkDiagramFitViewOptions,\n NetworkDiagramToImageOptions,\n NetworkDiagramFlowObject,\n} from '../types';\nimport { U_HEIGHT_PX, RACK_HEADER_HEIGHT } from '../utils/constants';\nimport {\n getReactFlowThemeClassName,\n getReactFlowBackgroundColor,\n getReactFlowWrapperStyle,\n type ColorMode,\n} from '../utils/react-flow-theming';\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 { 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';\nimport { isRackDeviceNode } from '../utils/rack-device-types';\nimport { isPowerEndpointHandle } from '../utils/endpoint-kind';\nimport { normalizeDirectionalHandleId } from '../utils/handle-ids';\nimport {\n getRackFaceGapPx,\n getRackFaceWidthPx,\n getRackMountMode,\n getVisibleFacesForMountMode,\n isSplitFaceRackLayout,\n} from '../utils/rack-layout';\nimport { resolveSplitRackMountModeForDrop } from '../utils/rack-mount-mode';\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 server: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"server\">\n <DeviceNode {...props} />\n </NodeWithDataType>\n ),\n switch: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"switch\">\n <DeviceNode {...props} />\n </NodeWithDataType>\n ),\n router: (props: NodeProps<NetworkNode['data']>) => (\n <NodeWithDataType type=\"router\">\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\nfunction isSwitchLikeNode(node?: NetworkNode): boolean {\n if (!node) {\n return false;\n }\n\n if (node.type === 'switch') {\n return true;\n }\n\n if (node.type !== 'device') {\n return false;\n }\n\n const deviceType = node.data?.deviceType;\n return typeof deviceType === 'string' && deviceType.toLowerCase().replace(/_/g, '-') === 'switch';\n}\n\n/**\n * In loose mode, dragging from target handles can yield connections where a switch\n * endpoint carries the opposite directional suffix for its side. Canonicalize to:\n * - switch source side => \"<port>\"\n * - switch target side => \"<port>-target\"\n */\nfunction normalizeSwitchPortConnection(\n connection: Connection,\n sourceNode?: NetworkNode,\n targetNode?: NetworkNode\n): Connection {\n let sourceHandle = connection.sourceHandle;\n let targetHandle = connection.targetHandle;\n\n if (isSwitchLikeNode(sourceNode) && sourceHandle && !isPowerEndpointHandle(sourceNode, sourceHandle)) {\n sourceHandle = normalizeDirectionalHandleId(sourceHandle);\n }\n\n if (isSwitchLikeNode(targetNode) && targetHandle && !isPowerEndpointHandle(targetNode, targetHandle)) {\n targetHandle = `${normalizeDirectionalHandleId(targetHandle)}-target`;\n }\n\n if (sourceHandle === connection.sourceHandle && targetHandle === connection.targetHandle) {\n return connection;\n }\n\n return {\n ...connection,\n sourceHandle,\n targetHandle,\n };\n}\n\nconst defaultEdgeTypes: EdgeTypes = {\n fiber: FiberEdge,\n ethernet: FiberEdge,\n power: PowerEdge,\n smoothstep: SmoothStepFiberEdge,\n step: StepFiberEdge,\n 'thick-cable': ThickCableEdge,\n};\n\nconst MAX_TO_IMAGE_WIDTH = 8192;\nconst MAX_TO_IMAGE_HEIGHT = 8192;\nconst MAX_TO_IMAGE_PADDING = 2048;\nconst MAX_TO_IMAGE_PIXEL_RATIO = 4;\n\nfunction clampNumericOption(value: number | undefined, min: number, max: number): number | undefined {\n if (typeof value !== 'number' || Number.isNaN(value)) return undefined;\n return Math.min(max, Math.max(min, value));\n}\n\nfunction normalizeToImageOptions(options?: NetworkDiagramToImageOptions): NetworkDiagramToImageOptions | undefined {\n if (!options) return undefined;\n\n return {\n ...options,\n width: clampNumericOption(options.width, 1, MAX_TO_IMAGE_WIDTH),\n height: clampNumericOption(options.height, 1, MAX_TO_IMAGE_HEIGHT),\n padding: clampNumericOption(options.padding, 0, MAX_TO_IMAGE_PADDING),\n pixelRatio: clampNumericOption(options.pixelRatio, 0.1, MAX_TO_IMAGE_PIXEL_RATIO),\n quality: clampNumericOption(options.quality, 0, 1),\n };\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 nodeTypes: externalNodeTypes,\n edgeTypes: externalEdgeTypes,\n onConnect: externalOnConnect,\n onEdgeUpdate: externalOnEdgeUpdate,\n isValidConnection: externalIsValidConnection,\n connectionMode: externalConnectionMode,\n onViewChange,\n onRackFaceChange,\n className,\n style,\n alignRacksToBottom,\n reAssignable = true,\n colorMode = 'dark',\n onInit,\n onFlowMethods,\n showDownloadButton = false,\n downloadButtonPosition = 'top-right',\n downloadButtonText = 'Download Image',\n downloadButtonStyle,\n useSmoothstepEdgesForTubes = false,\n readOnly = false,\n interaction,\n actionPanel,\n connectOnClick = true,\n panOnDrag = true,\n panOnScroll = true,\n zoomOnScroll = true,\n fitViewOptions,\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] = 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 const isReadOnly = readOnly === true;\n const interactionConfig = useMemo(() => {\n const defaults = {\n // Keep node dragging available on touch devices.\n nodesDraggable: true,\n nodesConnectable: true,\n elementsSelectable: !isMobile,\n edgesFocusable: !isMobile,\n edgesReconnectable: true,\n connectOnClick,\n panOnDrag,\n panOnScroll: panOnScroll && !isMobile,\n zoomOnScroll: zoomOnScroll && !isMobile,\n zoomOnPinch: !isMobile,\n zoomOnDoubleClick: !isMobile,\n allowKeyboardDelete: true,\n showControls: true,\n showMiniMap: !isMobile,\n showInteractiveControl: true,\n };\n\n const merged = { ...defaults, ...(interaction ?? {}) };\n if (!isReadOnly) {\n return merged;\n }\n\n return {\n ...merged,\n nodesDraggable: false,\n nodesConnectable: false,\n elementsSelectable: false,\n edgesFocusable: false,\n edgesReconnectable: false,\n connectOnClick: false,\n panOnDrag: false,\n panOnScroll: false,\n zoomOnScroll: false,\n zoomOnPinch: false,\n zoomOnDoubleClick: false,\n allowKeyboardDelete: false,\n showInteractiveControl: false,\n };\n }, [isMobile, connectOnClick, panOnDrag, panOnScroll, zoomOnScroll, interaction, isReadOnly]);\n\n const actionPanelConfig = useMemo(() => ({\n enabled: actionPanel?.enabled ?? true,\n showRearToggle: actionPanel?.showRearToggle ?? true,\n showDeRack: actionPanel?.showDeRack ?? true,\n }), [actionPanel]);\n \n // Get React Flow methods for save/restore\n const {\n toObject,\n setViewport,\n setNodes: setReactFlowNodes,\n setEdges: setReactFlowEdges,\n getNodes,\n getEdges,\n fitView,\n flowToScreenPosition,\n } = useReactFlow();\n \n // Expose React Flow methods to parent component\n useEffect(() => {\n if (onFlowMethods) {\n onFlowMethods({\n toObject: () => toObject() as NetworkDiagramFlowObject,\n setViewport,\n setNodes: (nodes: NetworkNode[]) => {\n setReactFlowNodes(nodes);\n localStore.setState({ nodes });\n },\n setEdges: (edges: NetworkEdge[]) => {\n setReactFlowEdges(edges);\n localStore.setState({ edges });\n },\n toImage: (options?: NetworkDiagramToImageOptions) => {\n if (!reactFlowWrapper.current) return Promise.reject(new Error('ReactFlow wrapper not available'));\n return toPng(reactFlowWrapper.current, normalizeToImageOptions(options));\n },\n getNodes: () => getNodes() as NetworkNode[],\n getEdges: () => getEdges() as NetworkEdge[],\n fitView: (options?: NetworkDiagramFitViewOptions) => {\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 [isDownloading, setIsDownloading] = useState(false);\n\n const onDownload = useCallback(() => {\n if (isDownloading) {\n return;\n }\n\n if (!reactFlowWrapper.current) {\n if (debug) {\n console.error('ReactFlow wrapper ref is not available');\n }\n return;\n }\n setIsDownloading(true);\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 }).finally(() => {\n setIsDownloading(false);\n });\n }, [colorMode, debug, isDownloading]);\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 {\n ...createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n ),\n ...(externalNodeTypes ?? {}),\n }\n );\n \n // Update nodeTypes ref only when stable callbacks change (they shouldn't, but just in case)\n useEffect(() => {\n nodeTypesRef.current = {\n ...createNodeTypes(\n onViewChangeStable,\n onRackFaceChangeStable,\n getDragOverRackIdStable\n ),\n ...(externalNodeTypes ?? {}),\n };\n }, [onViewChangeStable, onRackFaceChangeStable, getDragOverRackIdStable, externalNodeTypes]);\n \n const mergedEdgeTypes = useMemo(\n () => ({\n ...defaultEdgeTypes,\n ...(externalEdgeTypes ?? {}),\n }),\n [externalEdgeTypes]\n );\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 const getNodeParentId = useCallback((node: Node | null | undefined): string | undefined => {\n if (!node) return undefined;\n if (typeof node.parentId === 'string') {\n return node.parentId;\n }\n const legacyParent = (node as Node & { parentNode?: string }).parentNode;\n if (typeof legacyParent === 'string') {\n return legacyParent;\n }\n return undefined;\n }, []);\n\n const getParentRackNode = useCallback((node: Node | null | undefined): Node | undefined => {\n const parentId = getNodeParentId(node);\n if (!parentId) return undefined;\n const parentNode = getNodeById(parentId);\n if (!parentNode || parentNode.type !== 'rack') {\n return undefined;\n }\n return parentNode;\n }, [getNodeById, getNodeParentId]);\n\n const isSplitFaceRackNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || node.type !== 'rack') {\n return false;\n }\n return isSplitFaceRackLayout((node as NetworkNode).data);\n }, []);\n\n const isSplitFaceRackDeviceNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || !isRackDeviceNode(node as NetworkNode)) {\n return false;\n }\n const parentRack = getParentRackNode(node);\n if (!parentRack) {\n return false;\n }\n return isSplitFaceRackLayout((parentRack as NetworkNode).data);\n }, [getParentRackNode]);\n\n const isPatchPanelDeviceNode = useCallback((node: Node | null | undefined): boolean => {\n if (!node || node.type !== 'device') {\n return false;\n }\n\n const deviceType = (node.data as NetworkNode['data'] | undefined)?.deviceType;\n return typeof deviceType === 'string' && deviceType.toLowerCase().replace(/_/g, '-') === 'patch-panel';\n }, []);\n\n const commitNodes = useCallback((nextNodes: Node[]) => {\n latestNodesRef.current = nextNodes;\n const map = new Map<string, Node>();\n nextNodes.forEach((node) => {\n map.set(node.id, node);\n });\n nodesMapRef.current = map;\n setNodes(nextNodes);\n\n if (!isControlled) {\n localStore.setState({ nodes: nextNodes as NetworkNode[] });\n } else {\n externalOnNodesChange?.(nextNodes as NetworkNode[]);\n }\n }, [isControlled, localStore, setNodes, externalOnNodesChange]);\n\n const commitEdges = useCallback((nextEdges: Edge[]) => {\n latestEdgesRef.current = nextEdges;\n setEdges(nextEdges);\n\n if (!isControlled) {\n localStore.setState({ edges: nextEdges as NetworkEdge[] });\n } else {\n externalOnEdgesChange?.(nextEdges as NetworkEdge[]);\n }\n }, [isControlled, localStore, setEdges, externalOnEdgesChange]);\n\n const getAbsoluteNodePosition = useCallback((node: Node): { x: number; y: number } => {\n if (node.positionAbsolute) {\n return node.positionAbsolute;\n }\n\n let x = node.position?.x || 0;\n let y = node.position?.y || 0;\n let parentId = getNodeParentId(node);\n const seenParents = new Set<string>();\n\n while (parentId && !seenParents.has(parentId)) {\n seenParents.add(parentId);\n const parentNode = getNodeById(parentId);\n if (!parentNode) {\n break;\n }\n\n if (parentNode.positionAbsolute) {\n x += parentNode.positionAbsolute.x;\n y += parentNode.positionAbsolute.y;\n break;\n }\n\n x += parentNode.position?.x || 0;\n y += parentNode.position?.y || 0;\n parentId = getNodeParentId(parentNode);\n }\n\n return { x, y };\n }, [getNodeById, getNodeParentId]);\n\n const getRackDropPoint = useCallback((node: Node): { x: number; y: number } => {\n const absolute = getAbsoluteNodePosition(node);\n const width = node.width || 0;\n const height = node.height || 0;\n return {\n x: absolute.x + width / 2,\n y: absolute.y + height / 2,\n };\n }, [getAbsoluteNodePosition]);\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 isRackDeviceNode(node as NetworkNode) &&\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 deviceHeight = node.data.uHeight || 1;\n const calculatedPosition = calculateDevicePositionFromU(\n parentRack as NetworkNode,\n node.data.uPosition,\n deviceHeight,\n node.data\n );\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[]): Node[] | null => {\n if (isReadOnly) {\n return null;\n }\n\n const holderPositionUpdates = new Map<string, number>();\n const uPositionUpdates = new Map<string, number>();\n const parentExtentIds = new Set<string>();\n\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 parentExtentIds.add(node.id);\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 parentExtentIds.add(node.id);\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 holderPositionUpdates.set(node.id, snappedResult.holderPosition);\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n\n // Handle rack-mounted device positioning within rack\n if (node && isRackDeviceNode(node as NetworkNode) && node.parentId) {\n const parentRack = getNodeById(node.parentId);\n if (parentRack && parentRack.type === 'rack') {\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 uPositionUpdates.set(node.id, snappedResult.uPosition);\n }\n\n return { ...change, position: { x: snappedResult.x, y: snappedResult.y } };\n }\n }\n }\n return change;\n });\n\n const nextNodes = applyNodeChanges(updatedChanges, latestNodesRef.current).map((node) => {\n let updatedNode = node;\n\n if (parentExtentIds.has(node.id)) {\n updatedNode = {\n ...updatedNode,\n extent: 'parent' as const,\n };\n }\n\n const holderPosition = holderPositionUpdates.get(node.id);\n if (holderPosition !== undefined) {\n updatedNode = {\n ...updatedNode,\n data: {\n ...updatedNode.data,\n holderPosition,\n },\n };\n }\n\n const uPosition = uPositionUpdates.get(node.id);\n if (uPosition !== undefined) {\n updatedNode = {\n ...updatedNode,\n data: {\n ...updatedNode.data,\n uPosition,\n },\n };\n }\n\n return updatedNode;\n });\n\n latestNodesRef.current = nextNodes;\n const map = new Map<string, Node>();\n nextNodes.forEach((node) => {\n map.set(node.id, node);\n });\n nodesMapRef.current = map;\n setNodes(nextNodes);\n\n return nextNodes;\n }, [setNodes, getNodeById, isReadOnly]);\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 an ungrouped rack-device is over a rack\n const handleNodeDrag = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n const parentId = getNodeParentId(node);\n if (!reAssignable || !isRackDeviceNode(node as NetworkNode) || parentId) {\n setDragOverRackId(null);\n return;\n }\n\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const dropPoint = getRackDropPoint(node);\n const nearestRack = findNearestRack(dropPoint, racks);\n const nextRackId = nearestRack?.id ?? null;\n\n setDragOverRackId((currentRackId) => (currentRackId === nextRackId ? currentRackId : nextRackId));\n }, [reAssignable, getRackDropPoint, getNodeParentId]);\n\n // Handle drag end to assign ungrouped rack-mounted nodes into racks\n const handleNodeDragStop = useCallback((_event: React.MouseEvent, node: Node, _nodes: Node[]) => {\n setDragOverRackId(null);\n\n const parentId = getNodeParentId(node);\n if (!reAssignable || !isRackDeviceNode(node as NetworkNode) || parentId) {\n return;\n }\n\n const absolutePosition = getAbsoluteNodePosition(node);\n const racks = latestNodesRef.current\n .filter(n => n.type === 'rack')\n .map(n => n as NetworkNode);\n const dropPoint = getRackDropPoint(node);\n const nearestRack = findNearestRack(dropPoint, racks);\n const currentNodes = latestNodesRef.current;\n\n if (!nearestRack) {\n // Keep ungrouped as-is when dropped outside any rack.\n return;\n }\n\n const relativeToRack = {\n x: absolutePosition.x - nearestRack.position.x,\n y: absolutePosition.y - nearestRack.position.y,\n };\n\n const baseNode = (currentNodes.find((n) => n.id === node.id) || node) as NetworkNode<'device' | 'server' | 'switch' | 'router'>;\n const splitFaceRack = isSplitFaceRackLayout(nearestRack.data);\n const rackWidthPx = getRackFaceWidthPx(nearestRack.data);\n const rackFaceGapPx = getRackFaceGapPx(nearestRack.data);\n const nextMountMode = splitFaceRack\n ? resolveSplitRackMountModeForDrop(baseNode.data, relativeToRack.x, rackWidthPx, rackFaceGapPx)\n : 'both';\n const initialDeviceX = splitFaceRack && nextMountMode === 'front'\n ? rackWidthPx + rackFaceGapPx\n : 0;\n const nextView =\n nextMountMode === 'rear'\n ? 'rear'\n : nextMountMode === 'front'\n ? 'front'\n : (baseNode.data.view === 'front' || baseNode.data.view === 'rear' ? baseNode.data.view : undefined);\n const candidateNode: NetworkNode<'device' | 'server' | 'switch' | 'router'> = {\n ...baseNode,\n parentId: nearestRack.id,\n extent: 'parent',\n position: { x: initialDeviceX, y: relativeToRack.y },\n data: {\n ...baseNode.data,\n rackLayout: splitFaceRack ? 'split-face' : 'single-face',\n rackWidthPx,\n rackFaceGapPx,\n mountMode: nextMountMode,\n view: nextView,\n },\n };\n\n const nodesForSnapping = currentNodes\n .filter((n) => n.id !== node.id)\n .concat(candidateNode as unknown as Node) as NetworkNode[];\n const snapped = snapToUPosition(\n candidateNode,\n nearestRack,\n candidateNode.position,\n nodesForSnapping\n );\n\n const updatedNodes = currentNodes.map((currentNode) => {\n if (currentNode.id !== node.id) {\n return currentNode;\n }\n\n return {\n ...currentNode,\n parentId: nearestRack.id,\n extent: 'parent',\n position: { x: snapped.x, y: snapped.y },\n data: {\n ...currentNode.data,\n rackLayout: splitFaceRack ? 'split-face' : 'single-face',\n rackWidthPx,\n rackFaceGapPx,\n mountMode: nextMountMode,\n view: nextView,\n uPosition: snapped.uPosition ?? currentNode.data.uPosition,\n },\n } as Node;\n });\n\n commitNodes(updatedNodes);\n }, [reAssignable, getAbsoluteNodePosition, getRackDropPoint, commitNodes, getNodeParentId]);\n\n // Connection validation for React Flow - allows connections before onConnect validation\n const handleIsValidConnection = 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 (!fiberConnection) {\n // For non-fiber connections, final occupancy checks run in onConnect/onEdgeUpdate.\n // This keeps reconnect UX responsive, because isValidConnection does not receive oldEdge context.\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 handleConnect = useCallback(\n (params: Connection) => {\n if (isReadOnly) {\n return;\n }\n\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 normalizedParams = normalizeSwitchPortConnection(\n params,\n sourceNode as NetworkNode | undefined,\n targetNode as NetworkNode | undefined\n );\n\n const initialValidation = localStore.validateConnection({\n source: normalizedParams.source ?? null,\n target: normalizedParams.target ?? null,\n sourceHandle: normalizedParams.sourceHandle,\n targetHandle: normalizedParams.targetHandle,\n });\n if (!initialValidation.valid) {\n const isHandleOccupancyError = (initialValidation.reason ?? '').includes('already connected');\n if (!isHandleOccupancyError) {\n if (debug) {\n console.warn(`Connection rejected: ${initialValidation.reason}`);\n }\n return;\n }\n }\n\n const isPduSource = sourceNode?.type === 'vertical-pdu';\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n const sourceIsPowerEndpoint = isPowerEndpointHandle(sourceNode as NetworkNode | undefined, normalizedParams.sourceHandle);\n const targetIsPowerEndpoint = isPowerEndpointHandle(targetNode as NetworkNode | undefined, normalizedParams.targetHandle);\n const isPowerConnection = sourceIsPowerEndpoint && targetIsPowerEndpoint && hasPduEndpoint;\n const sourceNodeData = sourceNode?.data as NetworkNode['data'];\n const isSwitchSource =\n sourceNode?.type === 'switch' ||\n (sourceNode?.type === 'device' && sourceNodeData?.deviceType === 'switch');\n const looksLikePowerTarget = targetIsPowerEndpoint;\n const looksLikeNetworkTarget = !!normalizedParams.targetHandle && (\n normalizedParams.targetHandle.startsWith('net-') || \n normalizedParams.targetHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(normalizeDirectionalHandleId(normalizedParams.targetHandle)) // Custom port names like \"QSFP28-1\", \"Network-1\"\n );\n const looksLikeNetworkSource = !!normalizedParams.sourceHandle && (\n normalizedParams.sourceHandle.startsWith('net-') || \n normalizedParams.sourceHandle.startsWith('port-') || \n /^[A-Z0-9]+-\\d+$/i.test(normalizeDirectionalHandleId(normalizedParams.sourceHandle))\n );\n const isSwitchTarget = targetNode?.type === 'switch' ||\n (targetNode?.type === 'device' && (targetNode.data as NetworkNode['data'])?.deviceType === 'switch');\n const isPduTarget = targetNode?.type === 'vertical-pdu';\n const looksLikePowerSource = sourceIsPowerEndpoint;\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 = normalizedParams.sourceHandle === 'cable-button' && normalizedParams.targetHandle === 'cable-button';\n \n let edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable' = 'fiber';\n if (isPowerConnection) {\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(normalizedParams.target!, normalizedParams.targetHandle);\n } else {\n // Cable-to-tube or other: derive from source handle\n colorInfo = deriveFiberColorFromSource(normalizedParams.source!, normalizedParams.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, normalizedParams.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, normalizedParams.targetHandle);\n const sourceHandleAlreadyConnected = latestEdgesRef.current.some((e) => {\n if (e.source === normalizedParams.source) {\n return normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle;\n }\n if (e.target === normalizedParams.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 === normalizedParams.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle;\n }\n if (e.source === normalizedParams.target) {\n return normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle;\n }\n return false;\n });\n if (sourceHandleAlreadyConnected || targetHandleAlreadyConnected) {\n const edgesToRemove = new Set<string>();\n for (const edge of latestEdgesRef.current) {\n if (edge.source === normalizedParams.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.sourceHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === normalizedParams.source) {\n if (normalizeHandle(sourceNode as NetworkNode | undefined, edge.targetHandle) === normalizedSourceHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.source === normalizedParams.target) {\n if (normalizeHandle(targetNode as NetworkNode | undefined, edge.sourceHandle) === normalizedTargetHandle) {\n edgesToRemove.add(edge.id);\n continue;\n }\n }\n if (edge.target === normalizedParams.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(normalizedParams, filtered);\n if (edgeFromAddEdge.length === filtered.length) {\n if (debug) {\n console.warn('Handle replacement skipped: addEdge did not create a new edge', normalizedParams);\n }\n } else {\n const newEdge = edgeFromAddEdge[edgeFromAddEdge.length - 1];\n const zIndex = selectEdgeZIndex({ ...normalizedParams, 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 commitEdges([...edgeFromAddEdge.slice(0, -1), edgeWithMetadata]);\n if (debug) {\n console.log('Handle replacement: Replaced', edgesToRemove.size, 'edge(s)');\n }\n return;\n }\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 commitEdges(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 commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: edgeType,\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'source',\n data: { color: cableColor },\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n // Try replacing as target\n newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'thick-cable',\n selectEdgeZIndex,\n findBy: 'target',\n data: { color: cableColor },\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Try to replace existing edge on target for PDU power connections (PDU is source of connection)\n if (isPduSource && looksLikePowerTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Try to replace when connecting FROM server TO PDU (PDU is target; server's handle is edge's target)\n if (isPduTarget && looksLikePowerSource && params.source && params.sourceHandle && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'source',\n matchOn: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n // Allow replacing when connecting FROM device TO switch (Loose mode: user drags from server to switch)\n // The switch's handle is the edge's source, so we match on edge's source\n if (isSwitchTarget && looksLikeNetworkSource && params.source && params.sourceHandle && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n matchOn: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n\n const validation = localStore.validateConnection({\n source: normalizedParams.source ?? null,\n target: normalizedParams.target ?? null,\n sourceHandle: normalizedParams.sourceHandle,\n targetHandle: normalizedParams.targetHandle,\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: normalizedParams,\n edgeType: looksLikePowerTarget ? 'power' : 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n // Try to replace when connecting from server to PDU (server handle already connected)\n if (isPduTarget && params.source && params.sourceHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'power',\n selectEdgeZIndex,\n findBy: 'source',\n matchOn: 'target',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(newEdges);\n return;\n }\n }\n // Allow replacing when connecting from device to switch (switch is target; edge's switch end is source)\n if (isSwitchTarget && params.target && params.targetHandle) {\n const newEdges = replaceEdge({\n edges: latestEdgesRef.current,\n connection: normalizedParams,\n edgeType: 'fiber',\n selectEdgeZIndex,\n findBy: 'target',\n matchOn: 'source',\n data: edgeData,\n });\n if (newEdges) {\n commitEdges(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 === normalizedParams.source && e.sourceHandle === normalizedParams.sourceHandle) ||\n (e.target === normalizedParams.source && e.targetHandle === normalizedParams.sourceHandle)\n );\n const targetHandleAlreadyUsed = latestEdgesRef.current.some(\n (e) => (e.target === normalizedParams.target && e.targetHandle === normalizedParams.targetHandle) ||\n (e.source === normalizedParams.target && e.sourceHandle === normalizedParams.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(normalizedParams.sourceHandle || '', sourceNode as NetworkNode | undefined);\n const isTargetSpecialForReplacement = isSpecialHandleForReplacement(normalizedParams.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: normalizedParams.sourceHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.source === normalizedParams.source && e.sourceHandle === normalizedParams.sourceHandle) ||\n (e.target === normalizedParams.source && e.targetHandle === normalizedParams.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: normalizedParams.target,\n targetHandle: normalizedParams.targetHandle,\n existingEdges: latestEdgesRef.current.filter(\n (e) => (e.target === normalizedParams.target && e.targetHandle === normalizedParams.targetHandle) ||\n (e.source === normalizedParams.target && e.sourceHandle === normalizedParams.targetHandle)\n )\n });\n }\n return;\n }\n\n const edgeToAdd = {\n ...normalizedParams,\n type: edgeType,\n zIndex: selectEdgeZIndex({ ...normalizedParams, id: 'temp-id' } as NetworkEdge),\n data: edgeData,\n } as Connection;\n\n const newEdges = addEdge(edgeToAdd, latestEdgesRef.current);\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 commitEdges(newEdges);\n },\n [commitEdges, localStore, selectEdgeZIndex, getNodeById, debug, deriveFiberColorFromSource, useSmoothstepEdgesForTubes, isReadOnly]\n );\n\n // Handle edge updates (when user drags an edge endpoint to reconnect)\n const handleEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (isReadOnly) {\n return;\n }\n\n if (!newConnection.source || !newConnection.target || !newConnection.sourceHandle || !newConnection.targetHandle) {\n return;\n }\n\n const sourceNode = getNodeById(newConnection.source);\n const targetNode = getNodeById(newConnection.target);\n const normalizedConnection = normalizeSwitchPortConnection(\n newConnection,\n sourceNode as NetworkNode | undefined,\n targetNode as NetworkNode | undefined\n );\n const normalizedSourceHandle = normalizeHandle(sourceNode as NetworkNode | undefined, normalizedConnection.sourceHandle);\n const normalizedTargetHandle = normalizeHandle(targetNode as NetworkNode | undefined, normalizedConnection.targetHandle);\n const hasHandleOccupancyConflict = latestEdgesRef.current.some((e) => {\n if (e.id === oldEdge.id) return false;\n const matchesSource =\n (e.source === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle) ||\n (e.target === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle);\n const matchesTarget =\n (e.target === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle) ||\n (e.source === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle);\n return matchesSource || matchesTarget;\n });\n\n const validation = localStore.validateConnection({\n source: normalizedConnection.source ?? null,\n target: normalizedConnection.target ?? null,\n sourceHandle: normalizedConnection.sourceHandle,\n targetHandle: normalizedConnection.targetHandle,\n ignoreEdgeId: oldEdge.id,\n });\n if (!validation.valid) {\n const isHandleOccupancyError = (validation.reason ?? '').includes('already connected');\n if (!(isHandleOccupancyError && hasHandleOccupancyConflict)) {\n if (debug) {\n console.warn(`Edge update rejected: ${validation.reason}`);\n }\n return;\n }\n }\n\n const hasPduEndpoint = sourceNode?.type === 'vertical-pdu' || targetNode?.type === 'vertical-pdu';\n const sourceIsPowerEndpoint = isPowerEndpointHandle(sourceNode as NetworkNode | undefined, normalizedConnection.sourceHandle);\n const targetIsPowerEndpoint = isPowerEndpointHandle(targetNode as NetworkNode | undefined, normalizedConnection.targetHandle);\n const isPowerConnection = sourceIsPowerEndpoint && targetIsPowerEndpoint && hasPduEndpoint;\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 (isPowerConnection) {\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') {\n const colorInfo = deriveFiberColorFromSource(normalizedConnection.source!, normalizedConnection.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 const existingEdges = latestEdgesRef.current;\n const deduped = existingEdges.filter((e) => {\n if (e.id === oldEdge.id) return true;\n const matchesSource =\n (e.source === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.sourceHandle) === normalizedSourceHandle) ||\n (e.target === normalizedConnection.source &&\n normalizeHandle(sourceNode as NetworkNode | undefined, e.targetHandle) === normalizedSourceHandle);\n const matchesTarget =\n (e.target === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.targetHandle) === normalizedTargetHandle) ||\n (e.source === normalizedConnection.target &&\n normalizeHandle(targetNode as NetworkNode | undefined, e.sourceHandle) === normalizedTargetHandle);\n return !(matchesSource || matchesTarget);\n });\n\n const updated = deduped.map((e) => {\n if (e.id === oldEdge.id) {\n return {\n ...e,\n source: normalizedConnection.source!,\n target: normalizedConnection.target!,\n sourceHandle: normalizedConnection.sourceHandle,\n targetHandle: normalizedConnection.targetHandle,\n type: edgeType,\n data: edgeData !== undefined ? { ...e.data, ...edgeData } : e.data,\n zIndex: selectEdgeZIndex({ ...normalizedConnection, id: e.id, type: edgeType } as NetworkEdge),\n style: { ...e.style, zIndex: selectEdgeZIndex({ ...normalizedConnection, id: e.id, type: edgeType } as NetworkEdge) },\n };\n }\n return e;\n });\n commitEdges(updated);\n },\n [commitEdges, getNodeById, deriveFiberColorFromSource, selectEdgeZIndex, useSmoothstepEdgesForTubes, debug, localStore, isReadOnly]\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 const allNodes = getNodes();\n let selectedTarget = node;\n\n // If a tube is clicked and it has a parent cable, select the parent instead\n const parentId = getNodeParentId(node);\n if (node.type === 'tube' && parentId && !isCommandClick) {\n const parentNode = allNodes.find(n => n.id === parentId && (n.type === 'cable' || n.type === 'multi-tube-cable'));\n if (parentNode) {\n selectedTarget = parentNode;\n }\n }\n\n // Mirror selected node locally so action buttons do not depend on RF selection subscriptions.\n setSelectedNode(selectedTarget);\n setSelectedEdges([]);\n setNodes((nds) =>\n nds.map((n) => {\n const shouldSelect = n.id === selectedTarget.id;\n return n.selected === shouldSelect ? n : { ...n, selected: shouldSelect };\n })\n );\n\n if (isCommandClick && isRackDeviceNode(selectedTarget as NetworkNode) && !isSplitFaceRackDeviceNode(selectedTarget)) {\n const data = selectedTarget.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 ${selectedTarget.id} from ${currentView} to ${nextView}`);\n }\n\n // Use external onViewChange instead of internal state management\n if (onViewChange) {\n onViewChange(selectedTarget.id, nextView);\n }\n }\n\n onNodeClick && onNodeClick(selectedTarget as NetworkNode);\n },\n [onViewChange, onNodeClick, debug, getNodes, setNodes, isMobile, getNodeParentId, isSplitFaceRackDeviceNode]\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 setSelectedNode(null);\n setSelectedEdges([edge]);\n setNodes((nds) => nds.map((n) => (n.selected ? { ...n, selected: false } : n)));\n onNodeClick?.(null);\n if (onEdgeClick) {\n onEdgeClick(edge as NetworkEdge);\n }\n },\n [onEdgeClick, onNodeClick, setNodes]\n );\n\n const handlePaneClick = useCallback(() => {\n setSelectedNode(null);\n setSelectedEdges([]);\n setNodes((nds) => nds.map((n) => (n.selected ? { ...n, selected: false } : n)));\n onNodeClick?.(null);\n }, [onNodeClick, setNodes]);\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: ({ edges }) => {\n // Track selected edges for deletion\n setSelectedEdges(edges || []);\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 if (!interactionConfig.allowKeyboardDelete) {\n return;\n }\n\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 const remainingEdges = latestEdgesRef.current.filter(e => !edgeIdsToDelete.has(e.id));\n commitEdges(remainingEdges);\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, commitEdges, debug, interactionConfig.allowKeyboardDelete]);\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 (isReadOnly) return;\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 if (isSplitFaceRackLayout(nodeData)) {\n return;\n }\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 (isRackDeviceNode(node as NetworkNode)) {\n if (isSplitFaceRackDeviceNode(node)) {\n return;\n }\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, isReadOnly, isSplitFaceRackDeviceNode]);\n\n const deRackSelectedDevice = useCallback(() => {\n if (isReadOnly || !reAssignable || !selectedNode) return;\n if (!isRackDeviceNode(selectedNode)) return;\n\n const node = getNodeById(selectedNode.id);\n const parentId = getNodeParentId(node);\n if (!node || !isRackDeviceNode(node as NetworkNode) || !parentId) return;\n\n const absolutePosition = getAbsoluteNodePosition(node);\n const currentNodes = latestNodesRef.current;\n const updatedNodes = currentNodes.map((currentNode) => {\n if (currentNode.id !== node.id) {\n return currentNode;\n }\n\n return {\n ...currentNode,\n parentId: undefined,\n parentNode: undefined,\n extent: undefined,\n position: absolutePosition,\n data: {\n ...currentNode.data,\n uPosition: undefined,\n },\n } as Node;\n });\n\n commitNodes(updatedNodes);\n }, [isReadOnly, reAssignable, selectedNode, getNodeById, getAbsoluteNodePosition, commitNodes, getNodeParentId]);\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\n const resolveVisibleFaces = (node: Node | undefined): Array<'front' | 'rear'> | undefined => {\n if (!node || !isRackDeviceNode(node as NetworkNode)) {\n return undefined;\n }\n const nodeData = (node as NetworkNode).data ?? {};\n const parentId =\n typeof node.parentId === 'string'\n ? node.parentId\n : (node as Node & { parentNode?: string }).parentNode;\n const parentRack = parentId ? nodesMap.get(parentId) : undefined;\n if (parentRack && parentRack.type === 'rack' && isSplitFaceRackLayout((parentRack as NetworkNode).data)) {\n return getVisibleFacesForMountMode(getRackMountMode(nodeData));\n }\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' | undefined) || (hasRear && !hasFront ? 'rear' : 'front');\n return [view];\n };\n\n // Determine endpoint views\n const sourceVisibleFaces = resolveVisibleFaces(sourceNode);\n const targetVisibleFaces = resolveVisibleFaces(targetNode);\n const sourceIsPatchPanel = isPatchPanelDeviceNode(sourceNode);\n const targetIsPatchPanel = isPatchPanelDeviceNode(targetNode);\n const sourceHasMismatchedSide =\n isRackDeviceNode(sourceNode as NetworkNode | undefined) &&\n !sourceIsPatchPanel &&\n !!sourceVisibleFaces &&\n !!sourceSide &&\n !sourceVisibleFaces.includes(sourceSide);\n const targetHasMismatchedSide =\n isRackDeviceNode(targetNode as NetworkNode | undefined) &&\n !targetIsPatchPanel &&\n !!targetVisibleFaces &&\n !!targetSide &&\n !targetVisibleFaces.includes(targetSide);\n // Hide edges when either endpoint handle belongs to the opposite face.\n const hideForSource = sourceHasMismatchedSide;\n const hideForTarget = targetHasMismatchedSide;\n const shouldHide = hideForSource || hideForTarget;\n // Compose styles\n let nextStyle: React.CSSProperties | undefined = edge.style;\n if (shouldHide) {\n nextStyle = { ...edge.style, opacity: 0, pointerEvents: 'none' as const, zIndex: 0 };\n } else if (edge.style) {\n const isHiddenStyle =\n edge.style.opacity === 0 &&\n edge.style.pointerEvents === 'none' &&\n edge.style.zIndex === 0;\n if (isHiddenStyle) {\n const rest = { ...edge.style };\n delete rest.opacity;\n delete rest.pointerEvents;\n delete rest.zIndex;\n nextStyle = Object.keys(rest).length > 0 ? rest : undefined;\n }\n }\n return {\n ...edge,\n style: nextStyle,\n className: animatingEdges.has(edge.id) ? 'edge-connecting' : edge.className,\n };\n });\n }, [reactFlowEdges, animatingEdges, isPatchPanelDeviceNode]);\n\n const selectedNodeForActions = useMemo<Node | null>(() => {\n if (!selectedNode) {\n return null;\n }\n return getNodeById(selectedNode.id) ?? selectedNode;\n }, [selectedNode, getNodeById]);\n\n const selectedActionButtons = useMemo(() => {\n if (!selectedNodeForActions || !actionPanelConfig.enabled || isReadOnly) {\n return {\n showRearToggle: false,\n showDeRack: false,\n count: 0,\n };\n }\n\n const supportsRearToggle = (() => {\n if (selectedNodeForActions.type === 'rack') {\n return !isSplitFaceRackNode(selectedNodeForActions);\n }\n if (isRackDeviceNode(selectedNodeForActions)) {\n return !isSplitFaceRackDeviceNode(selectedNodeForActions);\n }\n return false;\n })();\n const showRearToggle = actionPanelConfig.showRearToggle && supportsRearToggle;\n const showDeRack =\n actionPanelConfig.showDeRack &&\n reAssignable &&\n !isReadOnly &&\n isRackDeviceNode(selectedNodeForActions) &&\n !!getNodeParentId(selectedNodeForActions);\n\n return {\n showRearToggle,\n showDeRack,\n count: (showRearToggle ? 1 : 0) + (showDeRack ? 1 : 0),\n };\n }, [selectedNodeForActions, actionPanelConfig, reAssignable, isReadOnly, getNodeParentId, isSplitFaceRackDeviceNode, isSplitFaceRackNode]);\n\n const actionPanelPosition = useMemo<{ left: number; top: number } | null>(() => {\n if (!selectedNodeForActions || selectedActionButtons.count === 0 || !reactFlowWrapper.current) {\n return null;\n }\n\n const wrapperRect = reactFlowWrapper.current.getBoundingClientRect();\n if (wrapperRect.width <= 0 || wrapperRect.height <= 0) {\n return null;\n }\n\n const absolute = selectedNodeForActions.positionAbsolute ?? getAbsoluteNodePosition(selectedNodeForActions);\n const nodeWidth = selectedNodeForActions.width || 0;\n const nodeHeight = selectedNodeForActions.height || 0;\n const panelWidth = selectedActionButtons.count > 1 ? 220 : 110;\n const panelHeight = 34;\n\n try {\n const topCenterAnchor = flowToScreenPosition({\n x: absolute.x + nodeWidth / 2,\n y: absolute.y,\n });\n const bottomCenterAnchor = flowToScreenPosition({\n x: absolute.x + nodeWidth / 2,\n y: absolute.y + nodeHeight,\n });\n\n let left = topCenterAnchor.x - wrapperRect.left - panelWidth / 2;\n let top = topCenterAnchor.y - wrapperRect.top - panelHeight - 10;\n\n // If there isn't enough space above, place below the node.\n if (top < 8) {\n top = bottomCenterAnchor.y - wrapperRect.top + 10;\n }\n\n left = Math.max(8, Math.min(left, wrapperRect.width - panelWidth - 8));\n top = Math.max(8, Math.min(top, wrapperRect.height - panelHeight - 8));\n\n return { left, top };\n } catch {\n return null;\n }\n }, [\n selectedNodeForActions,\n selectedActionButtons,\n getAbsoluteNodePosition,\n flowToScreenPosition,\n ]);\n\n const flowClassName = getReactFlowThemeClassName(colorMode as ColorMode, className);\n const wrapperStyle = getReactFlowWrapperStyle(colorMode as ColorMode, {\n touchAction: 'none', // Prevent default touch behaviors like scrolling\n ...style,\n });\n const connectHandler = externalOnConnect ?? handleConnect;\n const edgeUpdateHandler = externalOnEdgeUpdate ?? handleEdgeUpdate;\n const connectionValidator = externalIsValidConnection ?? handleIsValidConnection;\n\n return (\n <div \n ref={reactFlowWrapper} \n className={flowClassName}\n style={wrapperStyle}\n >\n <ReactFlow\n nodes={reactFlowNodes}\n edges={edgesWithAnimation}\n onNodesChange={(changes) => {\n if (isReadOnly) {\n return;\n }\n const nextNodes = handleNodesChange(changes);\n if (!nextNodes) {\n return;\n }\n if (!isControlled) {\n localStore.setState({ nodes: nextNodes as NetworkNode[] });\n } else {\n externalOnNodesChange && externalOnNodesChange(nextNodes as NetworkNode[]);\n }\n }}\n onEdgesChange={(changes) => {\n if (isReadOnly) {\n return;\n }\n\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 const nextEdges = applyEdgeChanges(filteredChanges, latestEdgesRef.current);\n onEdgesChange(filteredChanges);\n if (!isControlled) {\n localStore.setState({ edges: nextEdges as NetworkEdge[] });\n } else {\n externalOnEdgesChange && externalOnEdgesChange(nextEdges as NetworkEdge[]);\n }\n }\n }}\n onConnect={isReadOnly ? undefined : connectHandler}\n onConnectStart={handleConnectStart}\n onConnectEnd={handleConnectEnd}\n onEdgeUpdate={isReadOnly ? undefined : edgeUpdateHandler}\n isValidConnection={connectionValidator}\n connectionMode={externalConnectionMode}\n onNodeClick={handleNodeClick}\n onNodeDoubleClick={handleNodeDoubleClick}\n onPaneClick={handlePaneClick}\n onNodeDragStart={handleNodeDragStart}\n onNodeDrag={handleNodeDrag}\n onNodeDragStop={handleNodeDragStop}\n onEdgeClick={handleEdgeClick}\n onInit={onInit}\n nodeTypes={nodeTypesRef.current}\n edgeTypes={mergedEdgeTypes}\n defaultEdgeOptions={{\n zIndex: 1000,\n reconnectable: interactionConfig.edgesReconnectable\n }}\n nodesDraggable={interactionConfig.nodesDraggable}\n nodesConnectable={interactionConfig.nodesConnectable}\n elementsSelectable={interactionConfig.elementsSelectable}\n edgesFocusable={interactionConfig.edgesFocusable}\n elevateNodesOnSelect={false}\n selectNodesOnDrag={false}\n connectOnClick={interactionConfig.connectOnClick}\n panOnDrag={interactionConfig.panOnDrag}\n panOnScroll={interactionConfig.panOnScroll}\n zoomOnScroll={interactionConfig.zoomOnScroll}\n zoomOnPinch={interactionConfig.zoomOnPinch}\n zoomOnDoubleClick={interactionConfig.zoomOnDoubleClick}\n preventScrolling={isMobile}\n onlyRenderVisibleElements={true}\n fitView\n fitViewOptions={fitViewOptions}\n proOptions={{ hideAttribution: true }}\n >\n <Background color={getReactFlowBackgroundColor(colorMode as ColorMode)} />\n {interactionConfig.showControls && (\n <Controls showInteractive={interactionConfig.showInteractiveControl} />\n )}\n {interactionConfig.showMiniMap && <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 disabled={isDownloading}\n aria-busy={isDownloading}\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: isDownloading ? 'not-allowed' : 'pointer',\n opacity: isDownloading ? 0.7 : 1,\n transition: 'all 0.2s ease',\n ...downloadButtonStyle,\n }}\n >\n {isDownloading ? `${downloadButtonText}...` : downloadButtonText}\n </button>\n )}\n {selectedNodeForActions &&\n actionPanelPosition &&\n selectedActionButtons.count > 0 && (\n <div\n style={{\n position: 'absolute',\n top: actionPanelPosition.top,\n left: actionPanelPosition.left,\n display: 'flex',\n gap: 8,\n zIndex: 2000,\n }}\n >\n {selectedActionButtons.showRearToggle && (\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 = selectedNodeForActions.data as NetworkNode['data'];\n if (selectedNodeForActions.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 = selectedNodeForActions.data as NetworkNode['data'];\n if (selectedNodeForActions.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 )}\n {selectedActionButtons.showDeRack && (\n <button\n onClick={(e) => { e.preventDefault(); deRackSelectedDevice(); }}\n style={{\n background: '#7f1d1d',\n color: '#fee2e2',\n border: '1px solid #b91c1c',\n borderRadius: 4,\n padding: '6px 10px',\n fontSize: 11,\n fontFamily: 'monospace',\n cursor: 'pointer',\n }}\n title=\"Remove device from rack so it can be moved/reassigned\"\n >\n De-rack\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Main component for rendering interactive network diagrams.\n * \n * The NetworkDiagram component provides a complete solution for visualizing\n * network infrastructure including racks, devices, fiber connections, and power distribution.\n * \n * @example\n * ```tsx\n * import { NetworkDiagram, NetworkNode, NetworkEdge } from '@mp70/react-networks';\n * \n * const nodes: NetworkNode[] = [\n * {\n * id: 'rack-1',\n * type: 'rack',\n * position: { x: 100, y: 100 },\n * data: { label: 'Main Rack', uHeight: 42 }\n * }\n * ];\n * \n * <NetworkDiagram nodes={nodes} edges={[]} />\n * ```\n * \n * @public\n */\nexport const NetworkDiagram: React.FC<NetworkDiagramProps> = (props) => {\n return (\n <ReactFlowProvider>\n <NetworkDiagramInner {...props} />\n </ReactFlowProvider>\n );\n};\n","import React, { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface DiagramErrorBoundaryProps {\n /** Content to render when an error is caught */\n children: ReactNode;\n /** Optional fallback UI when an error occurs (default: simple message) */\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n /** Optional callback when an error is caught (e.g. for logging) */\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Error boundary that catches errors in the diagram tree (e.g. React Flow,\n * custom nodes) and renders a fallback instead of crashing the whole app.\n * Wrap &lt;NetworkDiagram&gt; (or the diagram subtree) with this for production.\n *\n * @example\n * ```tsx\n * <DiagramErrorBoundary\n * fallback={(error, reset) => (\n * <div>\n * <p>Diagram failed: {error.message}</p>\n * <button onClick={reset}>Try again</button>\n * </div>\n * )}\n * onError={(err, info) => logToService(err, info)}\n * >\n * <NetworkDiagram nodes={nodes} edges={edges} />\n * </DiagramErrorBoundary>\n * ```\n */\nexport class DiagramErrorBoundary extends Component<DiagramErrorBoundaryProps, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n this.props.onError?.(error, errorInfo);\n }\n\n reset = (): void => {\n this.setState({ error: null });\n };\n\n render(): ReactNode {\n const { error } = this.state;\n const { children, fallback } = this.props;\n\n if (error) {\n if (typeof fallback === 'function') {\n return fallback(error, this.reset);\n }\n if (fallback != null) {\n return fallback;\n }\n return (\n <div\n role=\"alert\"\n style={{\n padding: 16,\n margin: 8,\n border: '1px solid #e53e3e',\n borderRadius: 4,\n backgroundColor: '#fff5f5',\n color: '#c53030',\n }}\n >\n <strong>Diagram error</strong>: {error.message}\n <button\n type=\"button\"\n onClick={this.reset}\n style={{ marginLeft: 12, padding: '4px 8px', cursor: 'pointer' }}\n >\n Try again\n </button>\n </div>\n );\n }\n\n return children;\n }\n}\n","import { baseColorFor, fiberSolidOrStriped, getFiberColor, isStriped } from './fiber-colors';\nimport type { FibreFlowCable } from '../types/fibre-flow';\n\nexport interface FibreFlowRow {\n key: string;\n tubeIndex?: number;\n fiberIndex: number;\n y: number;\n color: string;\n striped: boolean;\n backgroundImage?: string;\n}\n\nexport interface FibreFlowTubeLabel {\n tubeIndex: number;\n y: number;\n label: string;\n color: string;\n}\n\nexport interface FibreFlowCableLayout {\n rows: FibreFlowRow[];\n tubeLabels: FibreFlowTubeLabel[];\n height: number;\n}\n\ninterface LayoutOptions {\n rowHeight: number;\n tubeGap: number;\n}\n\nexport function buildFibreFlowCableLayout(\n cable: FibreFlowCable,\n { rowHeight, tubeGap }: LayoutOptions\n): FibreFlowCableLayout {\n const rows: FibreFlowRow[] = [];\n const tubeLabels: FibreFlowTubeLabel[] = [];\n\n const kind = cable.kind ?? (cable.tubeCount ? 'tube' : 'simple');\n const tubeCount = kind === 'tube' ? Math.max(1, Math.min(24, cable.tubeCount ?? 1)) : 1;\n const fibersPerTube =\n kind === 'tube'\n ? Math.max(1, Math.min(24, cable.fibersPerTube ?? 12))\n : Math.max(1, Math.min(24, cable.fiberCount ?? 12));\n const tubeStartIndex = Math.max(1, cable.tubeStartIndex ?? 1);\n const fiberStartIndex = Math.max(1, cable.fiberStartIndex ?? 1);\n\n let currentY = 0;\n\n for (let tubeOffset = 0; tubeOffset < tubeCount; tubeOffset += 1) {\n const tubeIndex = tubeStartIndex + tubeOffset;\n const tubeColor = cable.tubeColorMap?.[tubeIndex];\n tubeLabels.push({\n tubeIndex,\n y: currentY,\n label: `T${tubeIndex}`,\n color: tubeColor ?? baseColorFor(tubeIndex),\n });\n\n for (let fiberOffset = 0; fiberOffset < fibersPerTube; fiberOffset += 1) {\n const fiberIndex = fiberStartIndex + fiberOffset;\n const style = fiberSolidOrStriped(fiberIndex);\n rows.push({\n key: `${tubeIndex}-${fiberIndex}`,\n tubeIndex: kind === 'tube' ? tubeIndex : undefined,\n fiberIndex,\n y: currentY,\n color: getFiberColor(fiberIndex),\n striped: isStriped(fiberIndex),\n backgroundImage: typeof style.backgroundImage === 'string' ? style.backgroundImage : undefined,\n });\n currentY += rowHeight;\n }\n\n if (tubeOffset < tubeCount - 1) {\n currentY += tubeGap;\n }\n }\n\n return {\n rows,\n tubeLabels,\n height: currentY,\n };\n}\n","import React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n addEdge,\n BaseEdge,\n Connection,\n ConnectionMode,\n Edge,\n EdgeLabelRenderer,\n EdgeProps,\n Handle,\n NodeProps,\n Position,\n getBezierPath,\n} from 'reactflow';\nimport { NetworkDiagram } from './NetworkDiagram';\nimport type {\n FibreFlowCableNodeData as BaseFibreFlowCableNodeData,\n FibreFlowClosureNodeData,\n NetworkEdge,\n NetworkNode,\n} from '../types';\nimport type { FibreFlowCircuit, FibreFlowClosure, FibreFlowEndpoint } from '../types/fibre-flow';\nimport { buildFibreFlowCableLayout, FibreFlowCableLayout } from '../utils/fibre-flow-layout';\nimport { getFiberColor, isStriped } from '../utils/fiber-colors';\n\ntype FibreFlowLayoutDirection = 'horizontal' | 'vertical';\ntype FibreFlowColorMode = 'dark' | 'light';\n\ntype FibreFlowCableNodeData = Omit<BaseFibreFlowCableNodeData, 'layout'> & {\n layout: FibreFlowCableLayout;\n};\n\ninterface FibreFlowEdgeData {\n label?: string;\n lossDb?: number;\n color?: string;\n sourceColor?: string; // Color from source fiber handle\n targetColor?: string; // Color from target fiber handle\n sourceStriped?: boolean;\n targetStriped?: boolean;\n highlighted?: boolean;\n dimmed?: boolean;\n circuitId?: string;\n circuitLabel?: string;\n showCircuitId?: boolean;\n}\n\ninterface FibreFlowLinkEdgeData {\n label?: string;\n color?: string;\n}\n\ntype FibreFlowMapNode =\n | NetworkNode<'fibre-flow-cable', FibreFlowCableNodeData>\n | NetworkNode<'fibre-flow-closure', FibreFlowClosureNodeData>;\ntype FibreFlowMapEdgeType = 'fibre-flow' | 'fibre-flow-link';\ntype FibreFlowMapEdge = Omit<NetworkEdge<FibreFlowEdgeData | FibreFlowLinkEdgeData>, 'type'> & {\n type: FibreFlowMapEdgeType;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null;\n};\n\nconst isFibreFlowNode = (node: NetworkNode): node is FibreFlowMapNode => {\n if (!isRecord(node.data)) {\n return false;\n }\n\n if (node.type === 'fibre-flow-cable') {\n const data = node.data as Partial<FibreFlowCableNodeData>;\n return (\n typeof data.label === 'string' &&\n isRecord(data.cable) &&\n (data.side === 'left' || data.side === 'right') &&\n typeof data.rowHeight === 'number' &&\n typeof data.columnWidth === 'number' &&\n typeof data.showTubeLabels === 'boolean' &&\n typeof data.showFiberNumbers === 'boolean' &&\n isRecord(data.layout)\n );\n }\n\n if (node.type === 'fibre-flow-closure') {\n const data = node.data as Partial<FibreFlowClosureNodeData>;\n return (\n typeof data.label === 'string' &&\n typeof data.width === 'number' &&\n typeof data.height === 'number' &&\n typeof data.headerHeight === 'number'\n );\n }\n\n return false;\n};\n\nconst isFibreFlowEdgeType = (\n edgeType: NetworkEdge['type'] | undefined\n): edgeType is FibreFlowMapEdgeType => {\n return edgeType === 'fibre-flow' || edgeType === 'fibre-flow-link';\n};\n\nconst hasEdgeEndpoints = (\n edge: NetworkEdge\n): edge is NetworkEdge & { id: string; source: string; target: string } => {\n return (\n typeof edge.id === 'string' &&\n edge.id.length > 0 &&\n typeof edge.source === 'string' &&\n edge.source.length > 0 &&\n typeof edge.target === 'string' &&\n edge.target.length > 0\n );\n};\n\nconst inferFibreFlowEdgeType = (edge: NetworkEdge): FibreFlowMapEdgeType => {\n if (edge.sourceHandle === 'cable-run' || edge.targetHandle === 'cable-run') {\n return 'fibre-flow-link';\n }\n return 'fibre-flow';\n};\n\nexport const normalizeFibreFlowEdges = (\n nextEdges: NetworkEdge[],\n previousEdges: FibreFlowMapEdge[] = []\n): FibreFlowMapEdge[] => {\n const previousById = new Map(previousEdges.map((edge) => [edge.id, edge] as const));\n const normalized: FibreFlowMapEdge[] = [];\n\n nextEdges.forEach((edge) => {\n if (!hasEdgeEndpoints(edge)) {\n return;\n }\n\n const previous = previousById.get(edge.id);\n const edgeType = isFibreFlowEdgeType(edge.type)\n ? edge.type\n : previous?.type ?? inferFibreFlowEdgeType(edge);\n\n normalized.push({\n ...(previous ?? {}),\n ...edge,\n type: edgeType,\n });\n });\n\n return normalized;\n};\n\nexport interface FibreFlowMapProps {\n closures: FibreFlowClosure[];\n circuits?: FibreFlowCircuit[];\n highlightedCircuitId?: string;\n layout?: FibreFlowLayoutDirection;\n rowHeight?: number;\n tubeGap?: number;\n closureGap?: number;\n cableColumnWidth?: number;\n spliceAreaWidth?: number;\n showTubeLabels?: boolean;\n showFiberNumbers?: boolean;\n colorMode?: FibreFlowColorMode;\n showCircuitId?: boolean;\n className?: string;\n style?: React.CSSProperties;\n readOnly?: boolean;\n panOnDrag?: boolean;\n panOnScroll?: boolean;\n zoomOnScroll?: boolean;\n}\n\nconst handleIdForEndpoint = (endpoint: FibreFlowEndpoint): string => {\n const tube = endpoint.tube ?? 1;\n return `fiber-${tube}-${endpoint.fiber}`;\n};\n\n/**\n * Get fiber color from an endpoint\n */\nconst getFiberColorFromEndpoint = (endpoint: FibreFlowEndpoint): string => {\n return getFiberColor(endpoint.fiber);\n};\n\n/**\n * Check if an endpoint has a striped pattern (fibers 13-24)\n */\nconst isStripedEndpoint = (endpoint: FibreFlowEndpoint): boolean => {\n return isStriped(endpoint.fiber);\n};\n\nconst formatDistanceLabel = (distanceMeters?: number, distanceLabel?: string): string | undefined => {\n if (distanceLabel) return distanceLabel;\n if (typeof distanceMeters !== 'number' || Number.isNaN(distanceMeters)) return undefined;\n if (distanceMeters >= 1000) {\n return `${(distanceMeters / 1000).toFixed(1)} km`;\n }\n return `${Math.round(distanceMeters)} m`;\n};\n\nexport const buildFibreFlowStripeDasharray = (\n needsStripeFirstHalf: boolean,\n needsStripeSecondHalf: boolean,\n firstHalfDashPattern: string,\n secondHalfDashPattern: string,\n halfLength: number,\n approximatePathLength: number\n): string => {\n if (needsStripeFirstHalf) {\n return `${firstHalfDashPattern} ${approximatePathLength}`;\n }\n\n if (needsStripeSecondHalf) {\n // Leading 0 creates an initial gap so the solid first half is not overpainted by stripe stroke.\n return `0 ${halfLength} ${secondHalfDashPattern} ${approximatePathLength}`;\n }\n\n return '6 6';\n};\n\nconst FibreFlowEdge: React.FC<EdgeProps<FibreFlowEdgeData>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n curvature: 0.35,\n });\n\n const lossText = typeof data?.lossDb === 'number' ? `${data.lossDb.toFixed(2)} dB` : '';\n const labelText = data?.label ?? lossText;\n const sourceColor = data?.sourceColor;\n const targetColor = data?.targetColor;\n const edgeColor = data?.color ?? sourceColor ?? targetColor ?? '#94a3b8';\n const sourceStriped = data?.sourceStriped ?? false;\n const targetStriped = data?.targetStriped ?? false;\n const isHighlighted = data?.highlighted ?? true;\n const isDimmed = data?.dimmed ?? false;\n const circuitId = data?.circuitId;\n const circuitLabel = data?.circuitLabel ?? circuitId; // Use friendly label if available, fallback to ID\n const showCircuitId = data?.showCircuitId ?? false;\n\n // Check if we need a gradient (source and target colors are different)\n const needsGradient = sourceColor && targetColor && sourceColor !== targetColor;\n \n // Calculate gradient stop position based on label position\n // Use straight-line distance approximation for bezier path\n const dx = targetX - sourceX;\n const dy = targetY - sourceY;\n const totalDistance = Math.sqrt(dx * dx + dy * dy);\n const labelDx = labelX - sourceX;\n const labelDy = labelY - sourceY;\n const labelDistance = Math.sqrt(labelDx * labelDx + labelDy * labelDy);\n const gradientStopPercent = totalDistance > 0 ? (labelDistance / totalDistance) * 100 : 50;\n const gradientId = `fibre-flow-gradient-${id}`;\n\n // Determine stripe rendering: only on the half corresponding to the striped fibre\n const needsStripeFirstHalf = sourceStriped && !targetStriped;\n const needsStripeSecondHalf = targetStriped && !sourceStriped;\n const needsStripeFull = sourceStriped && targetStriped;\n \n // Calculate approximate path length for dash array positioning\n // Bezier curves are typically 10-30% longer than straight-line distance\n // Use a conservative estimate of 1.25x for better coverage\n const approximatePathLength = totalDistance * 1.25;\n const halfLength = approximatePathLength / 2;\n \n // Calculate dash pattern for half-edge rendering\n // Each dash-gap pair is 12px (6px dash + 6px gap)\n const dashGapPair = 12;\n // Add extra pairs to ensure full coverage of the half (20% buffer)\n const numPairsWithBuffer = Math.ceil((halfLength * 1.2) / dashGapPair);\n const firstHalfDashPattern = Array(numPairsWithBuffer).fill('6 6').join(' ');\n // For second half, ensure we have enough to fully cover it (20% buffer)\n const secondHalfNumPairs = Math.ceil((halfLength * 1.2) / dashGapPair);\n const secondHalfDashPattern = Array(secondHalfNumPairs).fill('6 6').join(' ');\n\n // Calculate label dimensions based on content\n const hasCircuitId = showCircuitId && circuitLabel;\n const labelWidth = Math.max(\n labelText ? labelText.length * 6.2 + 16 : 0,\n hasCircuitId ? (circuitLabel?.length || 0) * 5.5 + 16 : 0\n );\n const labelHeight = hasCircuitId ? 32 : 16;\n\n return (\n <>\n <defs>\n {needsGradient && (\n <linearGradient \n id={gradientId} \n x1={sourceX} \n y1={sourceY} \n x2={targetX} \n y2={targetY}\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\"0%\" stopColor={sourceColor} />\n <stop offset={`${gradientStopPercent}%`} stopColor={sourceColor} />\n <stop offset={`${gradientStopPercent}%`} stopColor={targetColor} />\n <stop offset=\"100%\" stopColor={targetColor} />\n </linearGradient>\n )}\n </defs>\n {needsGradient ? (\n <path\n id={id}\n d={edgePath}\n fill=\"none\"\n stroke={`url(#${gradientId})`}\n strokeWidth={isHighlighted ? 4.0 : 3.0}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n opacity={isDimmed ? 0.25 : 1.0}\n strokeOpacity={isDimmed ? 0.25 : 1.0}\n style={{\n mixBlendMode: 'normal',\n }}\n />\n ) : (\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: edgeColor,\n strokeWidth: isHighlighted ? 4.0 : 3.0, // Increased for better visibility and solid appearance\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n opacity: isDimmed ? 0.25 : 1.0, // Full opacity for highlighted, increased for dimmed\n strokeOpacity: isDimmed ? 0.25 : 1.0, // SVG-specific opacity for better rendering\n mixBlendMode: 'normal', // Ensure normal blending mode\n }}\n />\n )}\n {/* Stripe overlay - conditionally rendered on appropriate half */}\n {(needsStripeFull || needsStripeFirstHalf || needsStripeSecondHalf) && (\n <path\n id={`${id}-stripe`}\n d={edgePath}\n fill=\"none\"\n stroke=\"#000\"\n strokeWidth={isHighlighted ? 1.6 : 1.3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={\n buildFibreFlowStripeDasharray(\n needsStripeFirstHalf,\n needsStripeSecondHalf,\n firstHalfDashPattern,\n secondHalfDashPattern,\n halfLength,\n approximatePathLength\n )\n }\n strokeDashoffset={0}\n opacity={isDimmed ? 0.2 : 0.9}\n style={{\n mixBlendMode: 'normal',\n }}\n />\n )}\n {(labelText || hasCircuitId) && isHighlighted && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n width: labelWidth,\n height: labelHeight,\n background: 'rgba(248, 250, 252, 0.92)',\n border: '1px solid rgba(15, 23, 42, 0.4)',\n borderRadius: 4,\n fontSize: 10,\n fontFamily: 'monospace',\n color: 'rgba(15, 23, 42, 0.9)',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n pointerEvents: 'none',\n padding: '2px 4px',\n zIndex: 9999, // Ensure labels are on top of fibre edges\n }}\n >\n {labelText && (\n <div style={{ lineHeight: 1.2 }}>\n {labelText}\n </div>\n )}\n {hasCircuitId && (\n <div style={{ \n fontSize: 8, \n opacity: 0.8, \n lineHeight: 1.2,\n marginTop: labelText ? 2 : 0,\n }}>\n {circuitLabel}\n </div>\n )}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n};\n\nconst FibreFlowCableLinkEdge: React.FC<EdgeProps<FibreFlowLinkEdgeData>> = ({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n}) => {\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n curvature: 0.2,\n });\n\n const labelText = data?.label;\n const edgeColor = data?.color ?? '#64748b';\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: edgeColor,\n strokeWidth: 3.0, // Increased for better visibility\n opacity: 0.85, // Increased opacity\n strokeDasharray: '8 10',\n }}\n />\n {labelText && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: 'absolute',\n transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,\n padding: '2px 8px',\n background: 'rgba(30, 41, 59, 0.9)',\n border: `1px solid ${edgeColor}`,\n borderRadius: 10,\n fontSize: 10,\n fontFamily: 'monospace',\n color: '#e2e8f0',\n letterSpacing: 0.2,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n zIndex: 9999, // Ensure labels are on top of cable link edges\n }}\n >\n {labelText}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n};\n\nconst FibreFlowCableNode: React.FC<NodeProps<FibreFlowCableNodeData>> = ({ data }) => {\n const {\n cable,\n side,\n rowHeight,\n columnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout,\n colorMode = 'dark',\n } = data;\n \n const isLightMode = colorMode === 'light';\n\n const jacketWidth = 8;\n const handleSize = 12;\n const labelOffset = -1; // Reduced to move numbers closer to fibres\n const panelInset = 0;\n const jacketColor = cable.jacketColor ?? '#facc15';\n const hasTubes = (cable.kind ?? (cable.tubeCount ? 'tube' : 'simple')) === 'tube';\n const effectiveShowTubeLabels = showTubeLabels && hasTubes;\n\n const panelLeft = side === 'left' ? jacketWidth + panelInset : panelInset;\n const panelRight = side === 'right' ? jacketWidth + panelInset : panelInset;\n // Simple: LEFT cable = Position.Right (handles on right edge), RIGHT cable = Position.Left (handles on left edge)\n const handlePosition = side === 'left' ? Position.Right : Position.Left;\n\n const cableRunHandleStyle: React.CSSProperties = {\n width: 4,\n height: 4,\n borderRadius: '50%',\n background: jacketColor,\n border: `1px solid ${jacketColor}`,\n boxShadow: '0 0 1px rgba(0,0,0,0.4)',\n top: '50%',\n position: 'absolute',\n ...(side === 'left'\n ? { left: 0, transform: 'translate(-50%, -50%)' }\n : { right: 0, transform: 'translate(50%, -50%)' }),\n };\n\n return (\n <div\n style={{\n position: 'relative',\n width: columnWidth,\n height: layout.height,\n fontFamily: 'monospace',\n color: 'inherit',\n overflow: 'visible',\n }}\n >\n <div\n style={{\n position: 'absolute',\n top: -18,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n background: isLightMode ? 'rgba(248, 250, 252, 0.95)' : 'rgba(15, 23, 42, 0.9)',\n color: isLightMode ? '#1a1a1a' : '#f8fafc',\n padding: '2px 6px',\n borderRadius: 4,\n whiteSpace: 'nowrap',\n maxWidth: columnWidth,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n zIndex: 10,\n ...(side === 'right' ? { \n textAlign: 'right',\n } : {}),\n }}\n >\n {cable.label}\n </div>\n\n {/* Cable jacket container */}\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n width: jacketWidth,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n borderRadius: 4,\n background: hasTubes ? 'transparent' : jacketColor,\n border: `1px solid ${jacketColor}`,\n boxShadow: hasTubes ? 'none' : 'inset 0 0 3px rgba(0,0,0,0.3)',\n overflow: 'hidden',\n }}\n >\n {/* Individual tube segments within the cable jacket */}\n {hasTubes && layout.tubeLabels.map((tube, tubeIdx) => {\n // Find fibers in this tube\n const tubeRows = layout.rows.filter(\n (row) => row.tubeIndex === tube.tubeIndex\n );\n \n if (tubeRows.length === 0) return null;\n \n // Calculate tube segment position and height - align precisely with fibers\n const tubeTop = tubeRows[0].y;\n const tubeBottom = tubeRows[tubeRows.length - 1].y + rowHeight;\n const tubeHeight = tubeBottom - tubeTop;\n \n // Check if there's a gap after this tube (for tubeGap)\n const nextTube = layout.tubeLabels[tubeIdx + 1];\n const hasGapAfter = nextTube && (nextTube.y - tubeBottom) > 0;\n \n return (\n <div\n key={`tube-segment-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tubeTop,\n left: 0,\n right: 0,\n height: tubeHeight,\n background: tube.color,\n borderLeft: `2px solid ${tube.color}`,\n borderRight: `2px solid ${tube.color}`,\n borderTop: tubeIdx === 0 ? `2px solid ${tube.color}` : '1px solid rgba(0,0,0,0.15)',\n borderBottom: hasGapAfter ? '1px solid rgba(0,0,0,0.15)' : `2px solid ${tube.color}`,\n boxShadow: 'inset 0 0 3px rgba(0,0,0,0.1)',\n borderRadius: tubeIdx === 0 && !hasGapAfter ? '4px 4px 0 0' :\n tubeIdx === 0 ? '4px 4px 0 0' :\n !hasGapAfter ? '0 0 4px 4px' : '0',\n zIndex: 2,\n }}\n />\n );\n })}\n </div>\n\n {/* Panel border - removed background to prevent edge overlay effect */}\n {/* Only show border for visual separation without background overlay */}\n {!effectiveShowTubeLabels && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: panelLeft,\n right: panelRight,\n // Only border on the fiber side (opposite to jacket)\n // For left cable: border on right side, for right cable: border on left side\n ...(side === 'left' \n ? { borderRight: `1px solid ${jacketColor}` }\n : { borderLeft: `1px solid ${jacketColor}` }\n ),\n pointerEvents: 'none',\n zIndex: 0,\n }}\n />\n )}\n \n {/* Tube color borders wrapping around fibers with lower opacity */}\n {hasTubes && layout.tubeLabels.map((tube, _tubeIdx) => {\n // Find fibers in this tube\n const tubeRows = layout.rows.filter(\n (row) => row.tubeIndex === tube.tubeIndex\n );\n \n if (tubeRows.length === 0) return null;\n \n // Calculate tube border position and height - align with fibers\n const tubeTop = tubeRows[0].y;\n const tubeBottom = tubeRows[tubeRows.length - 1].y + rowHeight;\n const tubeHeight = tubeBottom - tubeTop;\n \n return (\n <div\n key={`tube-border-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tubeTop,\n left: panelLeft,\n right: panelRight,\n height: tubeHeight,\n // Border on the outside edge where fibers connect\n // For left cable: border on right side (outside), for right cable: border on left side (outside)\n ...(side === 'left' \n ? { borderRight: `2px solid ${tube.color}` }\n : { borderLeft: `2px solid ${tube.color}` }\n ),\n opacity: 0.5,\n pointerEvents: 'none',\n }}\n />\n );\n })}\n\n {/* Tube labels removed - not needed, saves space */}\n\n {layout.rows.map((row) => {\n const handleId = `fiber-${row.tubeIndex ?? 1}-${row.fiberIndex}`;\n const top = row.y + rowHeight / 2;\n \n // Handle style - position on edge like CouplerNode pattern\n const handleStyle: React.CSSProperties & { '--fiber-bg'?: string; '--fiber-bg-image'?: string } = {\n position: 'absolute',\n width: handleSize,\n height: handleSize,\n borderRadius: '50%',\n top: top,\n background: row.backgroundImage ? row.backgroundImage : row.color,\n backgroundColor: row.color,\n border: `2px solid ${row.color}`,\n boxShadow: '0 0 6px rgba(0,0,0,0.3)',\n // Position handle 50% over edge (centered on border) - exactly like CouplerNode\n ...(side === 'left' \n ? { right: -handleSize / 2 } // Right edge - handle center at edge, half outside\n : { left: -handleSize / 2 } // Left edge - handle center at edge, half outside\n ),\n transform: 'translateY(-50%)',\n zIndex: 1000,\n cursor: 'crosshair',\n '--fiber-bg': row.color,\n minWidth: handleSize,\n minHeight: handleSize,\n };\n\n if (row.backgroundImage) {\n handleStyle['--fiber-bg-image'] = row.backgroundImage;\n }\n\n // Position numbers inside the panel and anchor them to the fiber edge.\n // For left cables: handles are on the right edge, numbers should be to the left of handles\n // For right cables: handles are on the left edge, numbers should be to the right of handles\n // Handle is centered on edge (half outside, half inside), so position number at handleSize + offset\n const numberPosition: React.CSSProperties =\n side === 'left'\n ? { right: handleSize + labelOffset, textAlign: 'right' }\n : { left: handleSize + labelOffset, textAlign: 'left' };\n\n return (\n <React.Fragment key={row.key}>\n <Handle\n id={handleId}\n type=\"source\"\n position={handlePosition}\n className=\"fibre-flow-handle\"\n style={handleStyle}\n isConnectable={true}\n data-fiber-idx={row.fiberIndex}\n data-tube-idx={row.tubeIndex}\n data-fiber-color={row.color}\n />\n <Handle\n id={handleId}\n type=\"target\"\n position={handlePosition}\n className=\"fibre-flow-handle\"\n style={handleStyle}\n isConnectable={true}\n data-fiber-idx={row.fiberIndex}\n data-tube-idx={row.tubeIndex}\n data-fiber-color={row.color}\n />\n {showFiberNumbers && (\n <div\n style={{\n position: 'absolute',\n top: row.y + rowHeight / 2 - 6,\n ...numberPosition,\n fontSize: 8,\n fontWeight: 600,\n color: isLightMode ? 'rgba(15, 23, 42, 0.7)' : 'rgba(148, 163, 184, 0.95)',\n whiteSpace: 'nowrap',\n lineHeight: 1,\n }}\n >\n {row.fiberIndex}\n </div>\n )}\n </React.Fragment>\n );\n })}\n\n <Handle\n id=\"cable-run\"\n type=\"source\"\n position={side === 'left' ? Position.Left : Position.Right}\n className=\"cable-run-handle\"\n style={cableRunHandleStyle}\n isConnectable={true}\n data-handle-type=\"cable-run\"\n />\n <Handle\n id=\"cable-run\"\n type=\"target\"\n position={side === 'left' ? Position.Left : Position.Right}\n className=\"cable-run-handle\"\n style={cableRunHandleStyle}\n isConnectable={true}\n data-handle-type=\"cable-run\"\n />\n </div>\n );\n};\n\nconst FibreFlowClosureNode: React.FC<NodeProps<FibreFlowClosureNodeData>> = ({ data }) => {\n const isLightMode = data.colorMode === 'light';\n return (\n <div\n style={{\n width: data.width,\n height: data.height,\n // Keep the body transparent so fibre edges stay fully saturated.\n background: 'transparent',\n border: isLightMode \n ? '1px solid rgba(148, 163, 184, 0.3)'\n : '1px solid rgba(148, 163, 184, 0.5)',\n borderRadius: 12,\n boxShadow: isLightMode\n ? '0 12px 24px rgba(0, 0, 0, 0.1)'\n : '0 12px 24px rgba(15, 23, 42, 0.2)',\n position: 'relative',\n pointerEvents: 'none',\n }}\n >\n <div\n style={{\n height: data.headerHeight,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'monospace',\n fontWeight: 700,\n fontSize: 12,\n letterSpacing: 0.6,\n textTransform: 'uppercase',\n color: isLightMode ? 'rgba(15, 23, 42, 0.9)' : 'rgba(226, 232, 240, 0.9)',\n background: isLightMode ? 'rgba(241, 245, 249, 0.7)' : 'rgba(15, 23, 42, 0.6)',\n borderBottom: isLightMode \n ? '1px solid rgba(148, 163, 184, 0.2)'\n : '1px solid rgba(148, 163, 184, 0.35)',\n borderTopLeftRadius: 12,\n borderTopRightRadius: 12,\n }}\n >\n {data.label}\n </div>\n </div>\n );\n};\n\nconst buildFlowNodes = (\n closures: FibreFlowClosure[],\n layout: FibreFlowLayoutDirection,\n rowHeight: number,\n tubeGap: number,\n closureGap: number,\n cableColumnWidth: number,\n spliceAreaWidth: number,\n showTubeLabels: boolean,\n showFiberNumbers: boolean,\n colorMode: FibreFlowColorMode = 'dark'\n): FibreFlowMapNode[] => {\n const nodes: FibreFlowMapNode[] = [];\n\n let cursor = 0;\n\n closures.forEach((closure) => {\n const leftLayout = buildFibreFlowCableLayout(closure.leftCable, { rowHeight, tubeGap });\n const rightLayout = buildFibreFlowCableLayout(closure.rightCable, { rowHeight, tubeGap });\n\n const bodyHeight = Math.max(leftLayout.height, rightLayout.height);\n const bodyWidth = cableColumnWidth * 2 + spliceAreaWidth;\n const headerHeight = 32;\n const padding = 16;\n const closureWidth = bodyWidth + padding * 2;\n const closureHeight = bodyHeight + headerHeight + padding * 2;\n\n const closureId = `flow-closure-${closure.id}`;\n const leftCableId = `flow-cable-${closure.id}-left`;\n const rightCableId = `flow-cable-${closure.id}-right`;\n\n const position =\n layout === 'horizontal'\n ? { x: cursor, y: 0 }\n : { x: 0, y: cursor };\n\n cursor += (layout === 'horizontal' ? closureWidth : closureHeight) + closureGap;\n\n const headerLabel = closure.chamberId ? `${closure.id} - ${closure.chamberId}` : closure.id;\n\n nodes.push({\n id: closureId,\n type: 'fibre-flow-closure',\n position,\n data: {\n label: headerLabel,\n width: closureWidth,\n height: closureHeight,\n headerHeight,\n colorMode,\n },\n selectable: false,\n draggable: false,\n style: {\n width: closureWidth,\n height: closureHeight,\n },\n });\n\n const leftOffsetY = headerHeight + padding + (bodyHeight - leftLayout.height) / 2;\n const rightOffsetY = headerHeight + padding + (bodyHeight - rightLayout.height) / 2;\n\n nodes.push({\n id: leftCableId,\n type: 'fibre-flow-cable',\n position: { x: padding, y: leftOffsetY },\n parentId: closureId,\n extent: 'parent',\n data: {\n label: closure.leftCable.label,\n cable: closure.leftCable,\n side: 'left',\n rowHeight,\n columnWidth: cableColumnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout: leftLayout,\n colorMode,\n },\n style: {\n width: cableColumnWidth,\n height: leftLayout.height,\n },\n });\n\n nodes.push({\n id: rightCableId,\n type: 'fibre-flow-cable',\n position: { x: padding + bodyWidth - cableColumnWidth, y: rightOffsetY },\n parentId: closureId,\n extent: 'parent',\n data: {\n label: closure.rightCable.label,\n cable: closure.rightCable,\n side: 'right',\n rowHeight,\n columnWidth: cableColumnWidth,\n showTubeLabels,\n showFiberNumbers,\n layout: rightLayout,\n colorMode,\n },\n style: {\n width: cableColumnWidth,\n height: rightLayout.height,\n },\n });\n\n });\n\n return nodes;\n};\n\nexport const buildFlowEdges = (\n closures: FibreFlowClosure[],\n circuits: FibreFlowCircuit[] | undefined,\n highlightedCircuitId: string | undefined,\n showCircuitId: boolean = false\n): FibreFlowMapEdge[] => {\n const edges: FibreFlowMapEdge[] = [];\n const circuitColorMap = new Map<string, string>();\n const circuitLabelMap = new Map<string, string>();\n const lastCableById = new Map<\n string,\n {\n nodeId: string;\n closureId: string;\n jacketColor?: string;\n distanceLabel?: string;\n distanceMeters?: number;\n }\n >();\n\n (circuits ?? []).forEach((circuit) => {\n if (circuit.color) {\n circuitColorMap.set(circuit.id, circuit.color);\n }\n if (circuit.label) {\n circuitLabelMap.set(circuit.id, circuit.label);\n }\n });\n\n closures.forEach((closure) => {\n const leftCableId = `flow-cable-${closure.id}-left`;\n const rightCableId = `flow-cable-${closure.id}-right`;\n const cables = [\n { nodeId: leftCableId, cable: closure.leftCable },\n { nodeId: rightCableId, cable: closure.rightCable },\n ];\n\n cables.forEach(({ nodeId, cable }) => {\n const previous = lastCableById.get(cable.id);\n if (previous && previous.closureId !== closure.id) {\n const label = formatDistanceLabel(\n cable.distanceMeters ?? previous.distanceMeters,\n cable.distanceLabel ?? previous.distanceLabel\n );\n const color = cable.jacketColor ?? previous.jacketColor ?? '#64748b';\n\n edges.push({\n id: `flow-link-${previous.nodeId}-${nodeId}`,\n type: 'fibre-flow-link',\n source: previous.nodeId,\n target: nodeId,\n sourceHandle: 'cable-run',\n targetHandle: 'cable-run',\n data: {\n label,\n color,\n },\n });\n }\n\n lastCableById.set(cable.id, {\n nodeId,\n closureId: closure.id,\n jacketColor: cable.jacketColor,\n distanceLabel: cable.distanceLabel,\n distanceMeters: cable.distanceMeters,\n });\n });\n\n closure.splices.forEach((splice) => {\n const isHighlighted = highlightedCircuitId\n ? splice.circuitId === highlightedCircuitId\n : true;\n const isDimmed = Boolean(highlightedCircuitId) && !isHighlighted;\n const circuitColor = splice.circuitId ? circuitColorMap.get(splice.circuitId) : undefined;\n const circuitLabel = splice.circuitId ? circuitLabelMap.get(splice.circuitId) : undefined;\n const edgeColor = splice.color ?? circuitColor;\n \n // Get source and target fiber colors\n const sourceColor = getFiberColorFromEndpoint(splice.from);\n const targetColor = getFiberColorFromEndpoint(splice.to);\n const sourceStriped = isStripedEndpoint(splice.from);\n const targetStriped = isStripedEndpoint(splice.to);\n\n edges.push({\n id: `flow-edge-${closure.id}-${splice.id}`,\n type: 'fibre-flow',\n source: leftCableId,\n target: rightCableId,\n sourceHandle: handleIdForEndpoint(splice.from),\n targetHandle: handleIdForEndpoint(splice.to),\n data: {\n lossDb: splice.lossDb,\n label: splice.label,\n color: edgeColor,\n sourceColor,\n targetColor,\n sourceStriped,\n targetStriped,\n highlighted: isHighlighted,\n dimmed: isDimmed,\n circuitId: splice.circuitId,\n circuitLabel,\n showCircuitId,\n },\n });\n });\n });\n\n return edges;\n};\n\nconst FibreFlowMapInner: React.FC<FibreFlowMapProps> = ({\n closures,\n circuits,\n highlightedCircuitId,\n layout = 'horizontal',\n rowHeight = 20,\n tubeGap = 10,\n closureGap = 140,\n cableColumnWidth = 32, // Reduced slightly: 8px jacket + 24px panel (handle 12px + number space ~12px)\n spliceAreaWidth = 260,\n showTubeLabels = true,\n showFiberNumbers = true,\n colorMode = 'dark',\n showCircuitId = false,\n className,\n style,\n readOnly = false,\n panOnDrag = true,\n panOnScroll = true,\n zoomOnScroll = true,\n}) => {\n const layoutNodes = useMemo(\n () =>\n buildFlowNodes(\n closures,\n layout,\n rowHeight,\n tubeGap,\n closureGap,\n cableColumnWidth,\n spliceAreaWidth,\n showTubeLabels,\n showFiberNumbers,\n colorMode\n ),\n [\n closures,\n layout,\n rowHeight,\n tubeGap,\n closureGap,\n cableColumnWidth,\n spliceAreaWidth,\n showTubeLabels,\n showFiberNumbers,\n colorMode,\n ]\n );\n\n const layoutEdges = useMemo(\n () => buildFlowEdges(closures, circuits, highlightedCircuitId, showCircuitId),\n [closures, circuits, highlightedCircuitId, showCircuitId]\n );\n\n const [nodes, setNodes] = useState(layoutNodes);\n const [edges, setEdges] = useState(layoutEdges);\n\n useEffect(() => {\n setNodes(layoutNodes);\n }, [layoutNodes, setNodes]);\n\n useEffect(() => {\n setEdges(layoutEdges);\n }, [layoutEdges, setEdges]);\n\n // Get fiber info (color and striped status) from a handle\n const getHandleFiberInfo = useCallback(\n (nodeId?: string | null, handleId?: string | null): { color: string; striped: boolean } | undefined => {\n if (!nodeId || !handleId || !handleId.startsWith('fiber-')) {\n return undefined;\n }\n const node = nodes.find((n) => n.id === nodeId);\n if (!node || node.type !== 'fibre-flow-cable') {\n return undefined;\n }\n const match = /^fiber-(\\d+)-(\\d+)$/.exec(handleId);\n if (!match) {\n return undefined;\n }\n const tubeIndex = Number(match[1]);\n const fiberIndex = Number(match[2]);\n const layout = (node.data as FibreFlowCableNodeData).layout;\n const row = layout.rows.find(\n (r) => (r.tubeIndex ?? 1) === tubeIndex && r.fiberIndex === fiberIndex\n );\n if (!row) {\n return undefined;\n }\n return { color: row.color, striped: row.striped ?? false };\n },\n [nodes]\n );\n\n // Validate connections - allow any fiber-to-fiber connections (any to any)\n const isValidConnection = useCallback(\n (connection: Connection): boolean => {\n if (readOnly) {\n return false;\n }\n\n if (!connection.source || !connection.target || !connection.sourceHandle || !connection.targetHandle) {\n return false;\n }\n\n // Find source and target nodes\n const sourceNode = nodes.find((n) => n.id === connection.source);\n const targetNode = nodes.find((n) => n.id === connection.target);\n\n if (!sourceNode || !targetNode) {\n return false;\n }\n\n // Check if both handles are fiber handles (format: \"fiber-<tube>-<fiber>\")\n const isSourceFiberHandle = typeof connection.sourceHandle === 'string' && connection.sourceHandle.startsWith('fiber-');\n const isTargetFiberHandle = typeof connection.targetHandle === 'string' && connection.targetHandle.startsWith('fiber-');\n const isCableRunHandle = connection.sourceHandle === 'cable-run' || connection.targetHandle === 'cable-run';\n\n // Allow cable-run connections\n if (isCableRunHandle) {\n return true;\n }\n\n // Allow any fiber-to-fiber connections (any cable to any cable)\n if (isSourceFiberHandle && isTargetFiberHandle) {\n const bothAreCables = sourceNode.type === 'fibre-flow-cable' && targetNode.type === 'fibre-flow-cable';\n return bothAreCables;\n }\n\n return false;\n },\n [nodes, readOnly]\n );\n\n const onConnect = useCallback(\n (params: Connection) => {\n if (readOnly) {\n return;\n }\n\n const isCableRun =\n params.sourceHandle === 'cable-run' || params.targetHandle === 'cable-run';\n const isFiberHandle = (handle?: string | null) =>\n typeof handle === 'string' && handle.startsWith('fiber-');\n const sourceIsFiber = isFiberHandle(params.sourceHandle);\n const targetIsFiber = isFiberHandle(params.targetHandle);\n const usesHandle = (e: Edge, nodeId?: string | null, handleId?: string | null) =>\n (e.source === nodeId && e.sourceHandle === handleId) ||\n (e.target === nodeId && e.targetHandle === handleId);\n\n // Get fiber info for manual connections\n const sourceInfo = !isCableRun ? getHandleFiberInfo(params.source, params.sourceHandle) : undefined;\n const targetInfo = !isCableRun ? getHandleFiberInfo(params.target, params.targetHandle) : undefined;\n \n const edgeData: FibreFlowEdgeData | undefined = !isCableRun\n ? {\n sourceColor: sourceInfo?.color,\n targetColor: targetInfo?.color,\n color: sourceInfo?.color ?? targetInfo?.color,\n sourceStriped: sourceInfo?.striped,\n targetStriped: targetInfo?.striped,\n }\n : undefined;\n\n setEdges((eds) => {\n const pruned = eds.filter((e) => {\n const sourceTaken = sourceIsFiber && usesHandle(e, params.source, params.sourceHandle);\n const targetTaken = targetIsFiber && usesHandle(e, params.target, params.targetHandle);\n return !(sourceTaken || targetTaken);\n });\n\n return addEdge(\n {\n ...params,\n type: isCableRun ? 'fibre-flow-link' : 'fibre-flow',\n data: edgeData,\n },\n pruned\n ) as FibreFlowMapEdge[];\n });\n },\n [getHandleFiberInfo, readOnly, setEdges]\n );\n\n // Handle edge reconnection (when dragging an edge endpoint to a new handle)\n const onEdgeUpdate = useCallback(\n (oldEdge: Edge, newConnection: Connection) => {\n if (readOnly) {\n return;\n }\n\n const isCableRun =\n newConnection.sourceHandle === 'cable-run' || newConnection.targetHandle === 'cable-run';\n \n // Get fiber info for the new connection\n const sourceInfo = !isCableRun ? getHandleFiberInfo(newConnection.source, newConnection.sourceHandle) : undefined;\n const targetInfo = !isCableRun ? getHandleFiberInfo(newConnection.target, newConnection.targetHandle) : undefined;\n \n const edgeData: FibreFlowEdgeData | undefined = !isCableRun\n ? {\n sourceColor: sourceInfo?.color,\n targetColor: targetInfo?.color,\n color: sourceInfo?.color ?? targetInfo?.color,\n sourceStriped: sourceInfo?.striped,\n targetStriped: targetInfo?.striped,\n }\n : undefined;\n\n const isFiberHandle = (handle?: string | null) =>\n typeof handle === 'string' && handle.startsWith('fiber-');\n const usesHandle = (e: Edge, nodeId?: string | null, handleId?: string | null) =>\n (e.source === nodeId && e.sourceHandle === handleId) ||\n (e.target === nodeId && e.targetHandle === handleId);\n\n setEdges((eds) => {\n // Remove the old edge\n const withoutOld = eds.filter((e) => e.id !== oldEdge.id);\n \n // Prune edges that use the new source handle\n const sourceIsFiber = isFiberHandle(newConnection.sourceHandle);\n const targetIsFiber = isFiberHandle(newConnection.targetHandle);\n const pruned = withoutOld.filter((e) => {\n const sourceTaken = sourceIsFiber && usesHandle(e, newConnection.source, newConnection.sourceHandle);\n const targetTaken = targetIsFiber && usesHandle(e, newConnection.target, newConnection.targetHandle);\n return !(sourceTaken || targetTaken);\n });\n\n // Add the updated edge\n return addEdge(\n {\n ...newConnection,\n type: isCableRun ? 'fibre-flow-link' : 'fibre-flow',\n data: edgeData,\n },\n pruned\n ) as FibreFlowMapEdge[];\n });\n },\n [getHandleFiberInfo, readOnly, setEdges]\n );\n\n const handleNodesChange = useCallback(\n (nextNodes: NetworkNode[]) => {\n if (readOnly) {\n return;\n }\n setNodes(nextNodes.filter(isFibreFlowNode));\n },\n [readOnly, setNodes]\n );\n\n const handleEdgesChange = useCallback(\n (nextEdges: NetworkEdge[]) => {\n if (readOnly) {\n return;\n }\n setEdges((previousEdges) => normalizeFibreFlowEdges(nextEdges, previousEdges));\n },\n [readOnly, setEdges]\n );\n\n const nodeTypes = useMemo(\n () => ({\n 'fibre-flow-cable': FibreFlowCableNode,\n 'fibre-flow-closure': FibreFlowClosureNode,\n }),\n []\n );\n\n const edgeTypes = useMemo(\n () => ({\n 'fibre-flow': FibreFlowEdge,\n 'fibre-flow-link': FibreFlowCableLinkEdge,\n }),\n []\n );\n\n const wrapperStyle: React.CSSProperties = {\n borderRadius: 8,\n overflow: 'hidden',\n ...style,\n };\n\n return (\n <NetworkDiagram\n nodes={nodes}\n edges={edges}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={onConnect}\n onEdgeUpdate={onEdgeUpdate}\n isValidConnection={isValidConnection}\n connectionMode={ConnectionMode.Loose}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n className={className}\n style={wrapperStyle}\n colorMode={colorMode}\n readOnly={readOnly}\n panOnDrag={panOnDrag}\n panOnScroll={panOnScroll}\n zoomOnScroll={zoomOnScroll}\n fitViewOptions={{ padding: 0.2 }}\n />\n );\n};\n\nexport const FibreFlowMap: React.FC<FibreFlowMapProps> = (props) => {\n return <FibreFlowMapInner {...props} />;\n};\n","import React, { useMemo } from 'react';\nimport type { FibreFlowCable } from '../types/fibre-flow';\nimport { buildFibreFlowCableLayout, FibreFlowCableLayout } from '../utils/fibre-flow-layout';\n\ninterface FibreCableWithTubesExpandedProps {\n cable: FibreFlowCable;\n side: 'left' | 'right';\n rowHeight?: number;\n tubeGap?: number;\n columnWidth?: number;\n layout?: FibreFlowCableLayout;\n showTubeLabels?: boolean;\n showFiberNumbers?: boolean;\n showCableLabel?: boolean;\n}\n\nexport const FibreCableWithTubesExpanded: React.FC<FibreCableWithTubesExpandedProps> = ({\n cable,\n side,\n rowHeight = 22,\n tubeGap = 10,\n columnWidth = 150,\n layout,\n showTubeLabels,\n showFiberNumbers = true,\n showCableLabel = true,\n}) => {\n const cableLayout = useMemo(\n () => layout ?? buildFibreFlowCableLayout(cable, { rowHeight, tubeGap }),\n [layout, cable, rowHeight, tubeGap]\n );\n\n const jacketWidth = 26;\n const portSize = 10;\n const portInset = 18;\n const innerPortX = side === 'left' ? columnWidth - portInset : portInset;\n const labelOffset = 8;\n const tubeLabelX = side === 'left' ? 6 : columnWidth - jacketWidth - 18;\n const jacketColor = cable.jacketColor ?? '#facc15';\n const useTubeLabels = showTubeLabels ?? (cable.kind ?? (cable.tubeCount ? 'tube' : 'simple')) === 'tube';\n\n return (\n <div\n style={{\n position: 'relative',\n width: columnWidth,\n height: cableLayout.height,\n fontFamily: 'monospace',\n color: 'inherit',\n }}\n >\n {showCableLabel && (\n <div\n style={{\n position: 'absolute',\n top: -18,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n background: 'rgba(15, 23, 42, 0.85)',\n color: '#f8fafc',\n padding: '2px 6px',\n borderRadius: 4,\n }}\n >\n {cable.label}\n </div>\n )}\n\n <div\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n width: jacketWidth,\n left: side === 'left' ? 0 : undefined,\n right: side === 'right' ? 0 : undefined,\n borderRadius: 14,\n background: `linear-gradient(90deg, ${jacketColor} 0%, ${jacketColor} 60%, rgba(0,0,0,0.25) 100%)`,\n border: `2px solid ${jacketColor}`,\n boxShadow: 'inset 0 0 6px rgba(0,0,0,0.4)',\n }}\n />\n\n {useTubeLabels &&\n cableLayout.tubeLabels.map((tube) => (\n <div\n key={`tube-${tube.tubeIndex}`}\n style={{\n position: 'absolute',\n top: tube.y + rowHeight / 2 - 6,\n left: tubeLabelX,\n fontSize: 9,\n fontWeight: 700,\n textTransform: 'uppercase',\n color: 'rgba(15, 23, 42, 0.75)',\n background: 'rgba(255, 255, 255, 0.6)',\n padding: '1px 6px 1px 4px',\n borderRadius: 10,\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n }}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: tube.color,\n border: '1px solid rgba(0, 0, 0, 0.4)',\n boxShadow: '0 0 3px rgba(0,0,0,0.25)',\n }}\n />\n <span>{tube.label}</span>\n </div>\n ))}\n\n {cableLayout.rows.map((row) => {\n const top = row.y + rowHeight / 2 - portSize / 2;\n const numberLeft =\n side === 'left' ? innerPortX - portSize / 2 - labelOffset : innerPortX + portSize / 2 + labelOffset;\n return (\n <React.Fragment key={row.key}>\n <div\n style={{\n position: 'absolute',\n top,\n left: innerPortX - portSize / 2,\n width: portSize,\n height: portSize,\n borderRadius: '50%',\n backgroundColor: row.color,\n backgroundImage: row.backgroundImage,\n border: '1px solid rgba(0, 0, 0, 0.4)',\n boxShadow: '0 0 4px rgba(0,0,0,0.25)',\n }}\n />\n {showFiberNumbers && (\n <div\n style={{\n position: 'absolute',\n top: row.y + rowHeight / 2 - 6,\n left: side === 'left' ? numberLeft : numberLeft,\n transform: side === 'left' ? 'translateX(-100%)' : 'none',\n fontSize: 10,\n fontWeight: 600,\n color: 'rgba(15, 23, 42, 0.75)',\n }}\n >\n {row.fiberIndex}\n </div>\n )}\n </React.Fragment>\n );\n })}\n </div>\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 {\n NetworkNode,\n NetworkEdge,\n NetBoxDevice,\n NetBoxRack,\n NetBoxCable,\n NetBoxInterface,\n NetBoxDeviceTransformOptions,\n NetBoxMappedPort,\n Port,\n PortBlock,\n PortCableType,\n PortType,\n} from '../types';\n\nconst resolveDeviceNodeId = (device: { id?: number; name: string }): string => {\n if (typeof device.id === 'number') {\n return `device-${device.id}`;\n }\n return `device-${device.name}`;\n};\n\ntype NodeStatus = 'active' | 'inactive' | 'maintenance';\ntype PortFace = 'front' | 'rear';\n\nconst DEFAULT_INTERFACE_GROUP = 'Interfaces';\nconst DEFAULT_MANAGEMENT_GROUP = 'Management';\nconst DEFAULT_POWER_GROUP = 'Power';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst toNonEmptyString = (value: unknown): string | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\nconst toNumber = (value: unknown): number | undefined => {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return undefined;\n};\n\nconst normalizeConnectorType = (value: unknown): Port['connectorType'] | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = value.trim().toUpperCase();\n if (normalized === 'C13' || normalized === 'C14' || normalized === 'C19' || normalized === 'C20') {\n return normalized;\n }\n return undefined;\n};\n\nconst normalizePortFace = (value: unknown): PortFace => {\n if (typeof value === 'string' && value.toLowerCase() === 'rear') {\n return 'rear';\n }\n return 'front';\n};\n\nconst getInterfaceCustomFields = (iface: NetBoxInterface): Record<string, unknown> | undefined =>\n isRecord(iface.custom_fields) ? iface.custom_fields : undefined;\n\nconst getNestedLayoutHints = (value: unknown): Record<string, unknown> | undefined =>\n isRecord(value) ? value : undefined;\n\nconst resolvePortFaceHint = (\n iface: NetBoxInterface,\n mappedFace?: NetBoxMappedPort['face']\n): PortFace => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n return normalizePortFace(\n mappedFace ??\n iface.layout?.face ??\n iface.face ??\n nestedLayout?.face ??\n customFields?.port_face ??\n customFields?.portFace ??\n customFields?.face\n );\n};\n\nconst resolvePortGroupHint = (\n iface: NetBoxInterface,\n type: PortType,\n mappedGroup?: string\n): string => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n const explicitGroup =\n toNonEmptyString(mappedGroup) ??\n toNonEmptyString(iface.layout?.group) ??\n toNonEmptyString(iface.port_group) ??\n toNonEmptyString(nestedLayout?.group) ??\n toNonEmptyString(customFields?.port_group) ??\n toNonEmptyString(customFields?.portGroup) ??\n toNonEmptyString(customFields?.interface_group) ??\n toNonEmptyString(customFields?.interfaceGroup) ??\n toNonEmptyString(customFields?.group);\n\n if (explicitGroup) {\n return explicitGroup;\n }\n if (type === 'power_ac' || type === 'power_c13' || type === 'power_c19') {\n return DEFAULT_POWER_GROUP;\n }\n if (type === 'console' || type === 'mgmt') {\n return DEFAULT_MANAGEMENT_GROUP;\n }\n return DEFAULT_INTERFACE_GROUP;\n};\n\nconst resolveConnectorTypeHint = (\n iface: NetBoxInterface,\n rawType?: string,\n mappedConnectorType?: NetBoxMappedPort['connectorType']\n): Port['connectorType'] | undefined => {\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n return (\n normalizeConnectorType(mappedConnectorType) ??\n normalizeConnectorType(iface.layout?.connectorType) ??\n normalizeConnectorType((iface.layout as unknown as Record<string, unknown> | undefined)?.connector_type) ??\n normalizeConnectorType(iface.connector_type) ??\n normalizeConnectorType(nestedLayout?.connectorType) ??\n normalizeConnectorType(nestedLayout?.connector_type) ??\n normalizeConnectorType(customFields?.connectorType) ??\n normalizeConnectorType(customFields?.connector_type) ??\n normalizeConnectorType(rawType)\n );\n};\n\nconst normalizePortType = (rawType: string | undefined, connectorType?: Port['connectorType']): PortType => {\n if (connectorType === 'C13') {\n return 'power_c13';\n }\n if (connectorType === 'C19') {\n return 'power_c19';\n }\n\n const normalized = (rawType ?? '').toLowerCase();\n if (normalized.includes('c13')) return 'power_c13';\n if (normalized.includes('c19')) return 'power_c19';\n if (normalized.includes('power') || normalized.includes('pdu')) return 'power_ac';\n if (\n normalized.includes('fiber') ||\n normalized.includes('sfp') ||\n normalized.includes('qsfp') ||\n normalized.includes('dac')\n ) return 'fiber';\n if (normalized.includes('console')) return 'console';\n if (normalized.includes('mgmt') || normalized.includes('management') || normalized.includes('oob')) return 'mgmt';\n if (normalized.includes('usb')) return 'usb';\n return 'ethernet';\n};\n\nconst normalizeCableType = (rawType: string | undefined): PortCableType | undefined => {\n const normalized = (rawType ?? '').toLowerCase();\n if (!normalized) return undefined;\n if (normalized.includes('om3')) return 'om3';\n if (normalized.includes('om4')) return 'om4';\n if (normalized.includes('om5')) return 'om5';\n if (normalized.includes('smf') || normalized.includes('singlemode')) return 'smf';\n if (normalized.includes('cat5e')) return 'cat5e';\n if (normalized.includes('cat6a')) return 'cat6a';\n if (normalized.includes('cat6')) return 'cat6';\n if (normalized.includes('cat7')) return 'cat7';\n if (normalized.includes('fiber') || normalized.includes('sfp') || normalized.includes('qsfp')) return 'fiber';\n if (\n normalized.includes('ethernet') ||\n normalized.includes('rj45') ||\n normalized.includes('1000base') ||\n normalized.includes('10gbase') ||\n normalized.includes('base-t')\n ) return 'ethernet';\n return undefined;\n};\n\nconst parsePortPosition = (value: unknown): Port['position'] | undefined => {\n if (!isRecord(value)) {\n return undefined;\n }\n\n const sideRaw = value.side ?? value.port_side ?? value.portSide;\n const side =\n typeof sideRaw === 'string' &&\n ['top', 'right', 'bottom', 'left'].includes(sideRaw.toLowerCase())\n ? (sideRaw.toLowerCase() as NonNullable<Port['position']>['side'])\n : undefined;\n\n const offsetPercent = toNumber(\n value.offsetPercent ??\n value.offset_percent ??\n value.offsetPct ??\n value.offset_pct\n );\n const offsetPx = toNumber(\n value.offsetPx ??\n value.offset_px ??\n value.offsetPixels ??\n value.offset_pixels\n );\n const xPercent = toNumber(\n value.xPercent ??\n value.x_percent ??\n value.xPct ??\n value.x_pct ??\n value.horizontalPercent ??\n value.horizontal_percent ??\n value.x\n );\n const yPercent = toNumber(\n value.yPercent ??\n value.y_percent ??\n value.yPct ??\n value.y_pct ??\n value.verticalPercent ??\n value.vertical_percent ??\n value.y\n );\n\n if (\n side === undefined &&\n offsetPercent === undefined &&\n offsetPx === undefined &&\n xPercent === undefined &&\n yPercent === undefined\n ) {\n return undefined;\n }\n\n return {\n side,\n offsetPercent,\n offsetPx,\n xPercent,\n yPercent,\n };\n};\n\nconst extractMappedPosition = (\n iface: NetBoxInterface,\n mappedPort: NetBoxMappedPort | null | undefined,\n includePortPositions: boolean\n): Port['position'] | undefined => {\n if (!includePortPositions) {\n return undefined;\n }\n\n const customFields = getInterfaceCustomFields(iface);\n const nestedLayout = getNestedLayoutHints(customFields?.layout);\n const candidates: unknown[] = [\n mappedPort?.position,\n mappedPort,\n iface.layout?.position,\n iface.layout,\n nestedLayout?.position,\n nestedLayout,\n customFields?.port_position,\n customFields?.portPosition,\n customFields?.position,\n customFields,\n iface as unknown as Record<string, unknown>,\n ];\n\n for (const candidate of candidates) {\n const parsed = parsePortPosition(candidate);\n if (parsed) {\n return parsed;\n }\n }\n\n return undefined;\n};\n\nconst defaultMapInterfaceToPort = (\n iface: NetBoxInterface,\n includePortPositions: boolean\n): NetBoxMappedPort => {\n const rawType = iface.type?.value ?? iface.type?.label ?? iface.layout?.type ?? undefined;\n const connectorType = resolveConnectorTypeHint(iface, rawType);\n const portType = normalizePortType(rawType, connectorType);\n const group = resolvePortGroupHint(iface, portType);\n\n return {\n label: iface.name,\n face: resolvePortFaceHint(iface),\n group,\n type: portType,\n cableType: normalizeCableType(rawType),\n connected: Boolean(iface.connected_endpoint || iface.cable),\n connectorType,\n position: extractMappedPosition(iface, undefined, includePortPositions),\n };\n};\n\nconst sortInterfaces = (interfaces: NetBoxInterface[]): NetBoxInterface[] => {\n return [...interfaces].sort((a, b) => {\n const aPosition = typeof a.position === 'number' ? a.position : Number.MAX_SAFE_INTEGER;\n const bPosition = typeof b.position === 'number' ? b.position : Number.MAX_SAFE_INTEGER;\n if (aPosition !== bPosition) {\n return aPosition - bPosition;\n }\n return a.name.localeCompare(b.name);\n });\n};\n\nconst upsertPortBlock = (portBlocks: PortBlock[], name: string): PortBlock => {\n const existing = portBlocks.find((block) => block.name === name);\n if (existing) {\n return existing;\n }\n const created: PortBlock = { name, ports: [] };\n portBlocks.push(created);\n return created;\n};\n\nconst buildInterfacePortBlocks = (\n device: NetBoxDevice,\n options: NetBoxDeviceTransformOptions\n): { front: PortBlock[]; rear: PortBlock[] } => {\n const { includePortPositions = false, mapInterfaceToPort } = options;\n const front: PortBlock[] = [];\n const rear: PortBlock[] = [];\n const sortedInterfaces = sortInterfaces(device.interfaces ?? []);\n\n sortedInterfaces.forEach((iface, index) => {\n const mappedPort = mapInterfaceToPort\n ? mapInterfaceToPort({ device, iface, index })\n : defaultMapInterfaceToPort(iface, includePortPositions);\n if (!mappedPort) {\n return;\n }\n\n const rawType = mappedPort.type ?? iface.type?.value ?? iface.type?.label ?? undefined;\n const connectorType = resolveConnectorTypeHint(iface, rawType, mappedPort.connectorType);\n const type = normalizePortType(rawType, connectorType);\n const targetFace = resolvePortFaceHint(iface, mappedPort.face);\n const groupName = resolvePortGroupHint(iface, type, mappedPort.group);\n\n const block = upsertPortBlock(targetFace === 'rear' ? rear : front, groupName);\n block.ports.push({\n id: mappedPort.id,\n label: mappedPort.label ?? iface.name,\n connected: mappedPort.connected ?? Boolean(iface.connected_endpoint || iface.cable),\n type,\n cableType: normalizeCableType(mappedPort.cableType ?? iface.type?.value ?? iface.type?.label ?? undefined),\n connectorType,\n position: extractMappedPosition(iface, mappedPort, includePortPositions),\n });\n });\n\n return { front, rear };\n};\n\n/**\n * Convert NetBox rack data to NetworkNode\n */\nexport const netboxRackToNetworkNode = (rack: NetBoxRack): NetworkNode => {\n return {\n id: `rack-${rack.id}`,\n type: 'rack',\n position: { x: 0, y: 0 }, // Will be set by layout\n data: {\n label: rack.name,\n status: rack.status.value as 'active' | 'inactive' | 'maintenance',\n uHeight: rack.u_height,\n netboxId: rack.id,\n netboxType: 'rack',\n // Additional NetBox data\n facilityId: rack.facility_id,\n serial: rack.serial,\n assetTag: rack.asset_tag,\n site: rack.site.name,\n role: rack.role?.name,\n tenant: rack.tenant?.name,\n },\n };\n};\n\n/**\n * Convert NetBox device data to NetworkNode\n */\nexport const netboxDeviceToNetworkNode = (\n device: NetBoxDevice,\n options: NetBoxDeviceTransformOptions = {}\n): NetworkNode => {\n const data: NetworkNode['data'] = {\n label: device.name,\n status: device.status.value as NodeStatus,\n deviceType: device.device_type.model,\n manufacturer: device.device_type.manufacturer.name,\n role: device.device_role.name,\n uHeight: 1, // Default, should be from device type\n uPosition: device.position || 1,\n face: device.face || 'front',\n netboxId: device.id,\n netboxType: 'device',\n // Additional NetBox data\n primaryIp4: device.primary_ip4?.address,\n primaryIp6: device.primary_ip6?.address,\n site: device.site.name,\n rack: device.rack?.name,\n };\n\n if (options.includeInterfacePorts && Array.isArray(device.interfaces) && device.interfaces.length > 0) {\n const { front, rear } = buildInterfacePortBlocks(device, options);\n if (front.length > 0) {\n data.ports = front;\n }\n if (rear.length > 0) {\n data.rearPorts = rear;\n }\n }\n\n return {\n id: `device-${device.id}`,\n type: 'device',\n position: { x: 0, y: 0 }, // Will be set by layout\n parentId: device.rack ? `rack-${device.rack.id}` : undefined,\n extent: device.rack ? 'parent' : undefined,\n data,\n };\n};\n\n/**\n * Convert NetBox cable data to NetworkEdge\n */\nexport const netboxCableToNetworkEdge = (cable: NetBoxCable): NetworkEdge => {\n return {\n id: `cable-${cable.id}`,\n source: resolveDeviceNodeId(cable.termination_a.device),\n target: resolveDeviceNodeId(cable.termination_b.device),\n type: 'fiber',\n data: {\n bandwidth: cable.type.label,\n length: cable.length || 0,\n color: cable.color,\n netboxId: cable.id,\n netboxType: 'cable',\n status: cable.status.value,\n terminationA: cable.termination_a.name,\n terminationB: cable.termination_b.name,\n },\n };\n};\n\n/**\n * Convert NetBox data to network diagram format\n */\nexport const netboxToNetworkDiagram = (data: {\n racks: NetBoxRack[];\n devices: NetBoxDevice[];\n cables: NetBoxCable[];\n}, options: NetBoxDeviceTransformOptions = {}): { nodes: NetworkNode[]; edges: NetworkEdge[] } => {\n const nodes: NetworkNode[] = [];\n const edges: NetworkEdge[] = [];\n const deviceNodeIdByName = new Map<string, string>();\n\n // Convert racks\n data.racks.forEach(rack => {\n nodes.push(netboxRackToNetworkNode(rack));\n });\n\n // Convert devices\n data.devices.forEach(device => {\n const deviceNode = netboxDeviceToNetworkNode(device, options);\n nodes.push(deviceNode);\n deviceNodeIdByName.set(device.name, deviceNode.id);\n });\n\n // Convert cables\n data.cables.forEach(cable => {\n const edge = netboxCableToNetworkEdge(cable);\n const sourceId =\n (typeof cable.termination_a.device.id === 'number' ? `device-${cable.termination_a.device.id}` : undefined) ??\n deviceNodeIdByName.get(cable.termination_a.device.name) ??\n edge.source;\n const targetId =\n (typeof cable.termination_b.device.id === 'number' ? `device-${cable.termination_b.device.id}` : undefined) ??\n deviceNodeIdByName.get(cable.termination_b.device.name) ??\n edge.target;\n edges.push({\n ...edge,\n source: sourceId,\n target: targetId,\n });\n });\n\n return { nodes, edges };\n};\n\n/**\n * Calculate U position for devices in a rack\n */\nexport const calculateUPositions = (devices: NetBoxDevice[], _rackHeight: number): Map<number, number> => {\n const positions = new Map<number, number>();\n const usedPositions = new Set<number>();\n\n // Sort devices by position\n const sortedDevices = devices\n .filter(d => d.position !== null)\n .sort((a, b) => (a.position || 0) - (b.position || 0));\n\n sortedDevices.forEach(device => {\n if (device.position) {\n positions.set(device.id, device.position);\n usedPositions.add(device.position);\n }\n });\n\n return positions;\n};\n\n/**\n * Generate layout positions for nodes\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 // Position racks\n rackNodes.forEach((rack, index) => {\n rack.position = { x: index * 300, y: 100 };\n });\n\n // Position devices relative to their parent racks\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 // Position orphaned devices\n device.position = { x: Math.random() * 400 + 100, y: Math.random() * 200 + 50 };\n }\n });\n\n // Position other nodes\n otherNodes.forEach((node, index) => {\n node.position = { x: index * 150 + 100, y: 300 };\n });\n\n return nodes;\n};\n","/**\n * Generic validation result structure\n */\nexport interface PlacementValidationResult<TConflict, TOutOfBounds> {\n isValid: boolean;\n conflicts: TConflict[];\n outOfBounds: TOutOfBounds[];\n}\n\n/**\n * Options for generic placement validation\n */\nexport interface PlacementValidationOptions<TItem, TConflict, TOutOfBounds> {\n items: TItem[];\n checkOutOfBounds: (item: TItem) => { isValid: boolean; error?: TOutOfBounds } | null;\n checkConflicts: (itemA: TItem, itemB: TItem) => { hasConflict: boolean; conflict?: TConflict } | null;\n}\n\n/**\n * Generic placement validation function\n * Validates items for out-of-bounds conditions and conflicts\n * \n * @param options - Validation options including items and checker functions\n * @returns Validation result with conflicts and out-of-bounds errors\n * \n * @example\n * ```ts\n * const result = validatePlacements({\n * items: devices,\n * checkOutOfBounds: (device) => {\n * if (device.unit + device.height > rack.units) {\n * return { isValid: false, error: { deviceId: device.id, ... } };\n * }\n * return null;\n * },\n * checkConflicts: (deviceA, deviceB) => {\n * if (overlaps(deviceA, deviceB)) {\n * return { hasConflict: true, conflict: { deviceId: deviceA.id, ... } };\n * }\n * return null;\n * }\n * });\n * ```\n */\nexport function validatePlacements<TItem, TConflict, TOutOfBounds>(\n options: PlacementValidationOptions<TItem, TConflict, TOutOfBounds>\n): PlacementValidationResult<TConflict, TOutOfBounds> {\n const { items, checkOutOfBounds, checkConflicts } = options;\n const conflicts: TConflict[] = [];\n const outOfBounds: TOutOfBounds[] = [];\n \n // Check for out-of-bounds placements\n for (const item of items) {\n const boundsCheck = checkOutOfBounds(item);\n if (boundsCheck && !boundsCheck.isValid && boundsCheck.error) {\n outOfBounds.push(boundsCheck.error);\n }\n }\n \n // Check for item-to-item conflicts\n for (let i = 0; i < items.length; i++) {\n const itemA = items[i];\n \n for (let j = i + 1; j < items.length; j++) {\n const itemB = items[j];\n const conflictCheck = checkConflicts(itemA, itemB);\n \n if (conflictCheck && conflictCheck.hasConflict && conflictCheck.conflict) {\n conflicts.push(conflictCheck.conflict);\n }\n }\n }\n \n return {\n isValid: conflicts.length === 0 && outOfBounds.length === 0,\n conflicts,\n outOfBounds,\n };\n}\n","import { NetworkNode, RackConfig, RackDevice, Width } from '../types';\nimport { validatePlacements } from './placement-validation';\nimport { calculateDevicePositionFromU, findNextAvailableUPosition } from './u-positioning';\nimport { isRackDeviceNodeType } from './rack-device-types';\nimport { getRackMountMode, isSplitFaceRackLayout, sharesMountedFace } from './rack-layout';\n\ntype RackMountedNodeType = 'device' | 'server' | 'switch' | 'router' | 'patch-panel' | 'vertical-pdu';\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, RackMountedNodeType>;\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 * \n * Checks for out-of-bounds placements and device-to-device conflicts.\n * Uses the generic validatePlacements utility for consistent validation logic.\n * \n * @param rack - The rack configuration to validate\n * @param _options - Validation options (currently unused)\n * @returns Validation result with conflicts and out-of-bounds errors\n * @public\n * \n * @example\n * ```ts\n * const rack: RackConfig = {\n * id: 'rack-1',\n * units: 42,\n * devices: [\n * { id: 'dev-1', unit: 1, height: 2, ... },\n * { id: 'dev-2', unit: 2, height: 1, ... } // Conflicts with dev-1\n * ]\n * };\n * const result = validateRackDevicePlacements(rack);\n * if (!result.isValid) {\n * console.log('Conflicts:', result.conflicts);\n * }\n * ```\n */\nexport function validateRackDevicePlacements(\n rack: RackConfig,\n _options: RackSchemaOptions = {}\n): DevicePlacementValidation {\n const splitFaceLayout = isSplitFaceRackLayout(rack);\n\n return validatePlacements({\n items: rack.devices,\n checkOutOfBounds: (device) => {\n const deviceEnd = device.unit + device.height - 1;\n if (deviceEnd > rack.units) {\n return {\n isValid: false,\n error: {\n deviceId: device.id,\n uPosition: device.unit,\n uHeight: device.height,\n rackUHeight: rack.units,\n },\n };\n }\n return null;\n },\n checkConflicts: (deviceA, deviceB) => {\n const deviceAStart = deviceA.unit;\n const deviceAEnd = deviceA.unit + deviceA.height - 1;\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 if (splitFaceLayout) {\n const mountModeA = getRackMountMode(deviceA);\n const mountModeB = getRackMountMode(deviceB);\n if (!sharesMountedFace(mountModeA, mountModeB)) {\n return null;\n }\n }\n\n return {\n hasConflict: true,\n conflict: {\n deviceId: deviceA.id,\n uPosition: deviceA.unit,\n uHeight: deviceA.height,\n conflictWith: deviceB.id,\n },\n };\n }\n return null;\n },\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<RackMountedNodeType> {\n const { deviceTypeMapping = {} } = options;\n \n // Map device type to NetworkNode type\n const nodeType: RackMountedNodeType = deviceTypeMapping[device.type] || 'device';\n \n // Calculate pixel position from U position\n const position = calculateDevicePositionFromU(rack, device.unit, device.height, device);\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: device.status || 'active',\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 frontImageUrl: device.frontImageUrl,\n rearImageUrl: device.rearImageUrl,\n frontImageAttribution: device.frontImageAttribution,\n rearImageAttribution: device.rearImageAttribution,\n imageFit: device.imageFit,\n imagePosition: device.imagePosition,\n imageRepeat: device.imageRepeat,\n stretchToFit: device.stretchToFit,\n rackWidthPx: rack.data.rackWidthPx, // Pass through parent rack's custom width\n rackLayout: rack.data.rackLayout,\n rackFaceGapPx: rack.data.rackFaceGapPx,\n mountMode: getRackMountMode(device),\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 rackLayout: rack.rackLayout,\n rackFaceGapPx: rack.rackFaceGapPx,\n },\n };\n}\n\n/**\n * Build NetworkNode array from RackConfig array with comprehensive validation\n * \n * Converts rack configurations to React Flow nodes with automatic validation\n * and conflict resolution. Supports strict and nearest conflict policies.\n * \n * @param racks - Array of rack configurations\n * @param options - Build options including conflict policy and validation settings\n * @returns Array of NetworkNode objects ready for React Flow\n * @throws {DevicePlacementError} If validation fails in strict mode\n * @public\n * \n * @example\n * ```ts\n * const racks: RackConfig[] = [{\n * id: 'rack-1',\n * name: 'Main Rack',\n * units: 42,\n * devices: [...]\n * }];\n * const nodes = buildNodesFromRackConfig(racks, {\n * conflictPolicy: 'strict',\n * validatePlacements: true\n * });\n * ```\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 {\n id: device.id,\n type: 'device',\n position: { x: 0, y: 0 },\n data: {\n label: device.name,\n uHeight: device.height,\n mountMode: getRackMountMode(device),\n },\n } 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 => isRackDeviceNodeType(node.type) && 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 === Width.FULL || deviceNode.data.width === Width.HALF\n ? deviceNode.data.width\n : undefined,\n ports: Array.isArray(deviceNode.data.ports) ? deviceNode.data.ports : undefined,\n connections: deviceNode.data.connections,\n frontImageUrl: deviceNode.data.frontImageUrl,\n rearImageUrl: deviceNode.data.rearImageUrl,\n frontImageAttribution: deviceNode.data.frontImageAttribution,\n rearImageAttribution: deviceNode.data.rearImageAttribution,\n imageFit: deviceNode.data.imageFit,\n imagePosition: deviceNode.data.imagePosition,\n imageRepeat: deviceNode.data.imageRepeat,\n stretchToFit: deviceNode.data.stretchToFit,\n mountMode: getRackMountMode(deviceNode.data),\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 rackLayout: rackNode.data.rackLayout,\n rackFaceGapPx: rackNode.data.rackFaceGapPx,\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 { validatePlacements } from './placement-validation';\nimport { calculateSplicePositionFromNumberWithData, findNextAvailableHolderPosition, HOLDERS_PER_TRAY, isHolderPositionAvailable } 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 * \n * Checks for out-of-bounds placements and splice-to-splice conflicts.\n * Uses the generic validatePlacements utility for consistent validation logic.\n * \n * @param tray - The splice tray configuration to validate\n * @param _options - Validation options (currently unused)\n * @returns Validation result with conflicts and out-of-bounds errors\n * @public\n * \n * @example\n * ```ts\n * const tray: SpliceTrayConfig = {\n * id: 'tray-1',\n * splices: [\n * { id: 'splice-1', holder: 1, ... },\n * { id: 'splice-2', holder: 1, ... } // Conflicts with splice-1\n * ]\n * };\n * const result = validateSplicePlacements(tray);\n * if (!result.isValid) {\n * console.log('Conflicts:', result.conflicts);\n * }\n * ```\n */\nexport function validateSplicePlacements(\n tray: SpliceTrayConfig,\n _options: SpliceSchemaOptions = {}\n): SplicePlacementValidation {\n return validatePlacements({\n items: tray.splices,\n checkOutOfBounds: (splice) => {\n if (splice.holder < 1 || splice.holder > HOLDERS_PER_TRAY) {\n return {\n isValid: false,\n error: {\n spliceId: splice.id,\n holder: splice.holder,\n max: HOLDERS_PER_TRAY,\n },\n };\n }\n return null;\n },\n checkConflicts: (spliceA, spliceB) => {\n // Check if two splices are in the same holder position\n if (spliceA.holder === spliceB.holder) {\n return {\n hasConflict: true,\n conflict: {\n spliceId: spliceA.id,\n holder: spliceA.holder,\n conflictWith: spliceB.id,\n },\n };\n }\n return null;\n },\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 * \n * Converts splice tray configurations to React Flow nodes with automatic validation\n * and conflict resolution. Supports strict and nearest conflict policies.\n * \n * @param trays - Array of splice tray configurations\n * @param options - Build options including conflict policy and validation settings\n * @returns Array of NetworkNode objects ready for React Flow\n * @throws {SplicePlacementError} If validation fails in strict mode\n * @public\n * \n * @example\n * ```ts\n * const trays: SpliceTrayConfig[] = [{\n * id: 'tray-1',\n * name: 'Tray 1',\n * splices: [...]\n * }];\n * const nodes = buildNodesFromSpliceConfig(trays, {\n * conflictPolicy: 'strict',\n * validatePlacements: true\n * });\n * ```\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 let resolvedHolder = splice.holder;\n if (conflictPolicy === 'nearest') {\n const placeholderSplice: NetworkNode = {\n id: splice.id,\n type: 'splice',\n position: { x: 0, y: 0 },\n data: { label: splice.name, holderPosition: splice.holder },\n };\n const allNodesForConflictCheck = [...nodes, ...spliceNodes];\n if (!isHolderPositionAvailable(trayNode, placeholderSplice, splice.holder, allNodesForConflictCheck)) {\n resolvedHolder = findNextAvailableHolderPosition(trayNode, placeholderSplice, allNodesForConflictCheck, splice.holder);\n }\n }\n const adjustedSplice = resolvedHolder !== splice.holder ? { ...splice, holder: resolvedHolder } : splice;\n const spliceNode = createSpliceNode(adjustedSplice, 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 * Template Schema V2 — unified device template model.\n *\n * Supports rackable devices (1U+), 0U/unrackable devices (vertical PDUs),\n * and hybrid front/rear pass-through devices. Strictly more expressive than\n * NetBox device-type YAML while remaining import-compatible.\n *\n * @public\n */\n\nimport type { PortType, PortCableType, PortPosition } from '../types';\n\n/** Current schema version constant. */\nexport const TEMPLATE_SCHEMA_VERSION = 2;\n\n/** Device mount class — distinguishes rackable from 0U/standalone devices. */\nexport type MountClass = 'rackable' | 'zero-u';\n\n/** Device width within a rack (full 19\" or half 9.5\"). */\nexport type TemplateWidth = 'full' | 'half';\n\n/**\n * Individual port inside a template port block.\n * @public\n */\nexport interface TemplatePort {\n /** Stable identifier for the port (must be unique within the template). */\n id: string;\n /** Human-readable label. */\n label: string;\n /** Port classification for styling and validation. */\n type?: PortType;\n /** Cable type hint. */\n cableType?: PortCableType;\n /** Power connector classification. */\n connectorType?: 'C13' | 'C14' | 'C19' | 'C20' | 'AC';\n /** Explicit handle placement. */\n position?: PortPosition;\n}\n\n/**\n * Group of related ports on a single face.\n * @public\n */\nexport interface TemplatePortBlock {\n /** Group name. */\n name: string;\n /** Ports in this group. */\n ports: TemplatePort[];\n}\n\n/**\n * Per-face data container for front or rear.\n * @public\n */\nexport interface TemplateFaceData {\n /** Port blocks on this face. */\n portBlocks: TemplatePortBlock[];\n /** Optional image URL for this face. */\n imageUrl?: string;\n /** Optional attribution for the image. */\n imageAttribution?: string;\n}\n\n/**\n * Explicit front-to-rear pass-through link between ports.\n * @public\n */\nexport interface TemplateFrontRearPortLink {\n /** Port ID on the front face. */\n frontPortId: string;\n /** Port ID on the rear face. */\n rearPortId: string;\n}\n\n/**\n * Source provenance for an imported template.\n * @public\n */\nexport interface TemplateSource {\n /** Source system kind (e.g. 'netbox', 'manual'). */\n kind: string;\n /** Source repository URL. */\n repository?: string;\n /** Path within the repository. */\n path?: string;\n}\n\n/**\n * Canonical device template schema V2.\n * @public\n */\nexport interface DeviceTemplateV2 {\n /** Schema version — always 2. */\n templateSchemaVersion: 2;\n /** Unique identifier (e.g. 'cisco-c9300-48p'). */\n id: string;\n /** URL-safe slug. */\n slug: string;\n /** Device manufacturer. */\n manufacturer: string;\n /** Device model. */\n model: string;\n /** Device role (e.g. 'switch', 'pdu', 'server'). */\n role: string;\n /** Mount class — rackable (1U+) or zero-u. */\n mountClass: MountClass;\n /** Height in rack units (0 for zero-u devices). */\n uHeight: number;\n /** Width within a rack. */\n width: TemplateWidth;\n /** Per-face port and image data. */\n faces: {\n front: TemplateFaceData;\n rear: TemplateFaceData;\n };\n /** Explicit front-to-rear pass-through links. */\n frontRearPortLinks: TemplateFrontRearPortLink[];\n /** Optional image configuration. */\n images?: {\n front?: string | null;\n rear?: string | null;\n };\n /** Source provenance. */\n source?: TemplateSource;\n /** Optional tags for search/filtering. */\n tags?: string[];\n}\n\n/**\n * Single validation issue from the parser pipeline.\n * @public\n */\nexport interface TemplateValidationIssue {\n /** Severity level. */\n severity: 'error' | 'warning';\n /** Machine-readable code. */\n code: string;\n /** Human-readable description. */\n message: string;\n /** Optional path to the problematic field. */\n path?: string;\n}\n\n/**\n * Validation report emitted by the parser pipeline.\n * @public\n */\nexport interface TemplateValidationReport {\n /** Whether the template is valid (no errors — warnings are allowed). */\n valid: boolean;\n /** List of issues found. */\n issues: TemplateValidationIssue[];\n /** Summary counts per face. */\n portCounts: {\n front: number;\n rear: number;\n };\n}\n\n/**\n * Result of the full parser pipeline.\n * @public\n */\nexport interface TemplateParseResult {\n /** Parsed template (present when valid). */\n template: DeviceTemplateV2 | null;\n /** Validation report. */\n report: TemplateValidationReport;\n}\n","/**\n * NetBox → Template V2 parser pipeline.\n *\n * Five stages: Ingest → Normalize → Enrich → Validate → Export.\n *\n * **Port position semantics**: Positions use `xPercent` / `yPercent` (0-100)\n * to express where the port CENTER should be relative to the device face.\n * The renderer (`DeviceNode`) converts these to pixel coordinates and clamps\n * them so the port stays fully inside the device bounds. Clamp bounds are\n * computed from the **actual** rendered port dimensions (which vary by port\n * type — e.g., power C13/C19 connectors are larger than generic ethernet\n * handles). Templates therefore do NOT need to account for port size; the\n * renderer handles that.\n *\n * @public\n */\n\nimport type { PortType } from '../types';\nimport {\n TEMPLATE_SCHEMA_VERSION,\n type DeviceTemplateV2,\n type MountClass,\n type TemplateFaceData,\n type TemplateFrontRearPortLink,\n type TemplateParseResult,\n type TemplatePort,\n type TemplatePortBlock,\n type TemplateSource,\n type TemplateValidationIssue,\n type TemplateValidationReport,\n type TemplateWidth,\n} from './template-schema';\n\n// ---------------------------------------------------------------------------\n// Public input type — what the parser accepts as raw NetBox-style data.\n// ---------------------------------------------------------------------------\n\n/**\n * Raw port entry from a NetBox-style template.\n * @public\n */\nexport interface RawTemplatePort {\n id?: string;\n name?: string;\n label?: string;\n type?: string;\n connectorType?: string;\n connector_type?: string;\n position?: {\n side?: string;\n offsetPercent?: number;\n offset_percent?: number;\n offsetPx?: number;\n offset_px?: number;\n xPercent?: number;\n x_percent?: number;\n yPercent?: number;\n y_percent?: number;\n };\n}\n\n/**\n * Raw port block from a NetBox-style template.\n * @public\n */\nexport interface RawTemplatePortBlock {\n name?: string;\n ports?: RawTemplatePort[];\n}\n\n/**\n * Raw NetBox-style template input for the parser.\n * @public\n */\nexport interface RawNetboxTemplate {\n id?: string;\n slug?: string;\n manufacturer?: string;\n model?: string;\n role?: string;\n deviceType?: string;\n device_type?: string;\n uHeight?: number;\n u_height?: number;\n width?: string;\n ports?: RawTemplatePortBlock[];\n rearPorts?: RawTemplatePortBlock[];\n rear_ports?: RawTemplatePortBlock[];\n frontRearPortLinks?: Array<{ frontPortId?: string; rearPortId?: string; front_port_id?: string; rear_port_id?: string }>;\n front_rear_port_links?: Array<{ frontPortId?: string; rearPortId?: string; front_port_id?: string; rear_port_id?: string }>;\n frontImageUrl?: string;\n front_image_url?: string;\n rearImageUrl?: string;\n rear_image_url?: string;\n frontImageAttribution?: string;\n rearImageAttribution?: string;\n tags?: string[];\n sourceRepository?: string;\n source_repository?: string;\n sourcePath?: string;\n source_path?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst toStr = (v: unknown): string =>\n typeof v === 'string' ? v.trim() : '';\n\nconst toFiniteNumber = (v: unknown): number | undefined => {\n if (typeof v === 'number' && Number.isFinite(v)) return v;\n return undefined;\n};\n\nconst normalizeConnector = (raw: unknown): TemplatePort['connectorType'] | undefined => {\n const s = toStr(raw).toUpperCase();\n if (s === 'C13' || s === 'C14' || s === 'C19' || s === 'C20' || s === 'AC') {\n return s as TemplatePort['connectorType'];\n }\n return undefined;\n};\n\nconst normalizePortType = (rawType: string | undefined, connector?: TemplatePort['connectorType']): PortType => {\n if (connector === 'C13' || connector === 'C14') return 'power_c13';\n if (connector === 'C19' || connector === 'C20') return 'power_c19';\n if (connector === 'AC') return 'power_ac';\n\n const n = (rawType ?? '').toLowerCase();\n if (n.includes('c13')) return 'power_c13';\n if (n.includes('c19')) return 'power_c19';\n if (n.includes('power') || n.includes('pdu')) return 'power_ac';\n if (n.includes('fiber') || n.includes('sfp') || n.includes('qsfp')) return 'fiber';\n if (n.includes('console')) return 'console';\n if (n.includes('mgmt') || n.includes('management')) return 'mgmt';\n if (n.includes('usb')) return 'usb';\n return 'ethernet';\n};\n\nconst inferConnectorFromType = (portType: PortType): TemplatePort['connectorType'] | undefined => {\n if (portType === 'power_c13') return 'C13';\n if (portType === 'power_c19') return 'C19';\n if (portType === 'power_ac') return 'AC';\n return undefined;\n};\n\nconst normalizeRole = (raw: string): string =>\n raw.toLowerCase().replace(/_/g, '-').trim();\n\nconst inferMountClass = (uHeight: number): MountClass =>\n uHeight >= 1 ? 'rackable' : 'zero-u';\n\nconst normalizeWidth = (raw: string | undefined): TemplateWidth => {\n const n = (raw ?? '').toLowerCase();\n return n === 'half' ? 'half' : 'full';\n};\n\nconst generatePortId = (face: 'front' | 'rear', blockIndex: number, portIndex: number, label: string): string => {\n const safeLabel = label.replace(/[^a-zA-Z0-9_-]/g, '-').toLowerCase();\n return `${face}-b${blockIndex}-${safeLabel || `p${portIndex}`}`;\n};\n\nconst generateSlug = (manufacturer: string, model: string): string =>\n `${manufacturer}-${model}`\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n\n// ---------------------------------------------------------------------------\n// Stage A: Ingest\n// ---------------------------------------------------------------------------\n\ninterface IngestResult {\n id: string;\n slug: string;\n manufacturer: string;\n model: string;\n role: string;\n uHeight: number;\n width: string | undefined;\n frontBlocks: RawTemplatePortBlock[];\n rearBlocks: RawTemplatePortBlock[];\n rawLinks: Array<{ frontPortId?: string; rearPortId?: string }>;\n frontImageUrl?: string;\n rearImageUrl?: string;\n frontImageAttribution?: string;\n rearImageAttribution?: string;\n tags: string[];\n sourceRepository?: string;\n sourcePath?: string;\n issues: TemplateValidationIssue[];\n}\n\nfunction stageIngest(raw: RawNetboxTemplate): IngestResult {\n const issues: TemplateValidationIssue[] = [];\n\n const manufacturer = toStr(raw.manufacturer);\n const model = toStr(raw.model);\n const role = toStr(raw.role) || toStr(raw.deviceType) || toStr(raw.device_type) || 'device';\n const uHeight = toFiniteNumber(raw.uHeight) ?? toFiniteNumber(raw.u_height) ?? 0;\n\n if (!manufacturer) issues.push({ severity: 'warning', code: 'MISSING_MANUFACTURER', message: 'Template is missing manufacturer', path: 'manufacturer' });\n if (!model) issues.push({ severity: 'warning', code: 'MISSING_MODEL', message: 'Template is missing model', path: 'model' });\n\n const id = toStr(raw.id) || toStr(raw.slug) || generateSlug(manufacturer, model) || 'unknown';\n const slug = toStr(raw.slug) || generateSlug(manufacturer, model) || id;\n\n const frontBlocks = Array.isArray(raw.ports) ? raw.ports : [];\n const rearBlocks = Array.isArray(raw.rearPorts) ? raw.rearPorts : (Array.isArray(raw.rear_ports) ? raw.rear_ports : []);\n\n const rawLinks = Array.isArray(raw.frontRearPortLinks)\n ? raw.frontRearPortLinks\n : (Array.isArray(raw.front_rear_port_links) ? raw.front_rear_port_links : []);\n const normalizedLinks = rawLinks.map((link) => ({\n frontPortId: toStr(link.frontPortId) || toStr(link.front_port_id),\n rearPortId: toStr(link.rearPortId) || toStr(link.rear_port_id),\n }));\n\n return {\n id,\n slug,\n manufacturer,\n model,\n role,\n uHeight,\n width: toStr(raw.width) || undefined,\n frontBlocks,\n rearBlocks,\n rawLinks: normalizedLinks,\n frontImageUrl: toStr(raw.frontImageUrl) || toStr(raw.front_image_url) || undefined,\n rearImageUrl: toStr(raw.rearImageUrl) || toStr(raw.rear_image_url) || undefined,\n frontImageAttribution: toStr(raw.frontImageAttribution) || undefined,\n rearImageAttribution: toStr(raw.rearImageAttribution) || undefined,\n tags: Array.isArray(raw.tags) ? raw.tags.map(toStr).filter(Boolean) : [],\n sourceRepository: toStr(raw.sourceRepository) || toStr(raw.source_repository) || undefined,\n sourcePath: toStr(raw.sourcePath) || toStr(raw.source_path) || undefined,\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage B: Normalize\n// ---------------------------------------------------------------------------\n\ninterface NormalizeResult {\n role: string;\n mountClass: MountClass;\n uHeight: number;\n width: TemplateWidth;\n frontFace: TemplateFaceData;\n rearFace: TemplateFaceData;\n issues: TemplateValidationIssue[];\n}\n\nfunction normalizePortBlock(\n rawBlock: RawTemplatePortBlock,\n face: 'front' | 'rear',\n blockIndex: number\n): TemplatePortBlock {\n const name = toStr(rawBlock.name) || `Block ${blockIndex + 1}`;\n const rawPorts = Array.isArray(rawBlock.ports) ? rawBlock.ports : [];\n const ports: TemplatePort[] = rawPorts.map((rawPort, portIndex) => {\n const label = toStr(rawPort.label) || toStr(rawPort.name) || `Port ${portIndex + 1}`;\n const rawConnector = normalizeConnector(rawPort.connectorType ?? rawPort.connector_type);\n const portType = normalizePortType(toStr(rawPort.type), rawConnector);\n const connectorType = rawConnector ?? inferConnectorFromType(portType);\n const portId = toStr(rawPort.id) || generatePortId(face, blockIndex, portIndex, label);\n\n const port: TemplatePort = {\n id: portId,\n label,\n type: portType,\n connectorType,\n };\n\n if (rawPort.position) {\n const pos = rawPort.position;\n const side = toStr(pos.side) as TemplatePort['position'] extends infer P ? P extends { side?: infer S } ? S : never : never;\n const position: TemplatePort['position'] = {};\n let hasPosition = false;\n\n if (side && ['top', 'right', 'bottom', 'left'].includes(side)) {\n position.side = side as 'top' | 'right' | 'bottom' | 'left';\n hasPosition = true;\n }\n\n const offsetPercent = toFiniteNumber(pos.offsetPercent) ?? toFiniteNumber(pos.offset_percent);\n if (offsetPercent !== undefined) { position.offsetPercent = offsetPercent; hasPosition = true; }\n\n const offsetPx = toFiniteNumber(pos.offsetPx) ?? toFiniteNumber(pos.offset_px);\n if (offsetPx !== undefined) { position.offsetPx = offsetPx; hasPosition = true; }\n\n const xPercent = toFiniteNumber(pos.xPercent) ?? toFiniteNumber(pos.x_percent);\n if (xPercent !== undefined) { position.xPercent = xPercent; hasPosition = true; }\n\n const yPercent = toFiniteNumber(pos.yPercent) ?? toFiniteNumber(pos.y_percent);\n if (yPercent !== undefined) { position.yPercent = yPercent; hasPosition = true; }\n\n if (hasPosition) {\n port.position = position;\n }\n }\n\n return port;\n });\n\n return { name, ports };\n}\n\nfunction stageNormalize(ingested: IngestResult): NormalizeResult {\n const issues: TemplateValidationIssue[] = [];\n const role = normalizeRole(ingested.role);\n const uHeight = ingested.uHeight;\n const mountClass = inferMountClass(uHeight);\n const width = normalizeWidth(ingested.width);\n\n const frontPortBlocks = ingested.frontBlocks.map((block, i) => normalizePortBlock(block, 'front', i));\n const rearPortBlocks = ingested.rearBlocks.map((block, i) => normalizePortBlock(block, 'rear', i));\n\n return {\n role,\n mountClass,\n uHeight,\n width,\n frontFace: {\n portBlocks: frontPortBlocks,\n imageUrl: ingested.frontImageUrl,\n imageAttribution: ingested.frontImageAttribution,\n },\n rearFace: {\n portBlocks: rearPortBlocks,\n imageUrl: ingested.rearImageUrl,\n imageAttribution: ingested.rearImageAttribution,\n },\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage C: Enrich\n// ---------------------------------------------------------------------------\n\ninterface EnrichResult {\n frontFace: TemplateFaceData;\n rearFace: TemplateFaceData;\n mountClass: MountClass;\n role: string;\n issues: TemplateValidationIssue[];\n}\n\nfunction addFacePrefixesIfNeeded(\n frontFace: TemplateFaceData,\n rearFace: TemplateFaceData\n): { front: TemplateFaceData; rear: TemplateFaceData } {\n const frontNames = new Set(frontFace.portBlocks.map((b) => b.name));\n const rearNames = new Set(rearFace.portBlocks.map((b) => b.name));\n const overlapping = [...frontNames].filter((name) => rearNames.has(name));\n\n if (overlapping.length === 0) {\n return { front: frontFace, rear: rearFace };\n }\n\n return {\n front: {\n ...frontFace,\n portBlocks: frontFace.portBlocks.map((block) =>\n overlapping.includes(block.name) ? { ...block, name: `Front · ${block.name}` } : block\n ),\n },\n rear: {\n ...rearFace,\n portBlocks: rearFace.portBlocks.map((block) =>\n overlapping.includes(block.name) ? { ...block, name: `Rear · ${block.name}` } : block\n ),\n },\n };\n}\n\nfunction stageEnrich(normalized: NormalizeResult): EnrichResult {\n const issues: TemplateValidationIssue[] = [];\n const { front, rear } = addFacePrefixesIfNeeded(normalized.frontFace, normalized.rearFace);\n\n let role = normalized.role;\n if (!role || role === 'device') {\n const hasPowerPorts = [...front.portBlocks, ...rear.portBlocks].some((block) =>\n block.ports.some((port) => port.type && port.type.startsWith('power'))\n );\n if (hasPowerPorts && normalized.mountClass === 'zero-u') {\n role = 'pdu';\n }\n }\n\n return {\n frontFace: front,\n rearFace: rear,\n mountClass: normalized.mountClass,\n role,\n issues,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage D: Validate\n// ---------------------------------------------------------------------------\n\nfunction countFacePorts(face: TemplateFaceData): number {\n return face.portBlocks.reduce((total, block) => total + block.ports.length, 0);\n}\n\nfunction stageValidate(\n ingested: IngestResult,\n enriched: EnrichResult\n): TemplateValidationReport {\n const issues: TemplateValidationIssue[] = [];\n\n // Unique port IDs\n const allPorts: Array<{ id: string; face: string }> = [];\n for (const block of enriched.frontFace.portBlocks) {\n for (const port of block.ports) {\n allPorts.push({ id: port.id, face: 'front' });\n }\n }\n for (const block of enriched.rearFace.portBlocks) {\n for (const port of block.ports) {\n allPorts.push({ id: port.id, face: 'rear' });\n }\n }\n\n const idCounts = new Map<string, number>();\n for (const { id } of allPorts) {\n idCounts.set(id, (idCounts.get(id) ?? 0) + 1);\n }\n for (const [id, count] of idCounts) {\n if (count > 1) {\n issues.push({\n severity: 'error',\n code: 'DUPLICATE_PORT_ID',\n message: `Duplicate port id \"${id}\" found ${count} times`,\n path: `ports.${id}`,\n });\n }\n }\n\n // Count parity against raw input\n const rawFrontCount = ingested.frontBlocks.reduce(\n (total, block) => total + (Array.isArray(block.ports) ? block.ports.length : 0),\n 0\n );\n const rawRearCount = ingested.rearBlocks.reduce(\n (total, block) => total + (Array.isArray(block.ports) ? block.ports.length : 0),\n 0\n );\n const parsedFrontCount = countFacePorts(enriched.frontFace);\n const parsedRearCount = countFacePorts(enriched.rearFace);\n\n if (parsedFrontCount !== rawFrontCount) {\n issues.push({\n severity: 'error',\n code: 'FRONT_PORT_COUNT_MISMATCH',\n message: `Front port count mismatch: raw=${rawFrontCount}, parsed=${parsedFrontCount}`,\n path: 'faces.front',\n });\n }\n if (parsedRearCount !== rawRearCount) {\n issues.push({\n severity: 'error',\n code: 'REAR_PORT_COUNT_MISMATCH',\n message: `Rear port count mismatch: raw=${rawRearCount}, parsed=${parsedRearCount}`,\n path: 'faces.rear',\n });\n }\n\n // Validate pass-through links reference existing port IDs\n const allPortIds = new Set(allPorts.map((p) => p.id));\n const frontPortIds = new Set(allPorts.filter((p) => p.face === 'front').map((p) => p.id));\n const rearPortIds = new Set(allPorts.filter((p) => p.face === 'rear').map((p) => p.id));\n\n for (const link of ingested.rawLinks) {\n if (link.frontPortId && !frontPortIds.has(link.frontPortId) && !allPortIds.has(link.frontPortId)) {\n issues.push({\n severity: 'warning',\n code: 'PASS_THROUGH_FRONT_PORT_MISSING',\n message: `Pass-through link references unknown front port \"${link.frontPortId}\"`,\n path: 'frontRearPortLinks',\n });\n }\n if (link.rearPortId && !rearPortIds.has(link.rearPortId) && !allPortIds.has(link.rearPortId)) {\n issues.push({\n severity: 'warning',\n code: 'PASS_THROUGH_REAR_PORT_MISSING',\n message: `Pass-through link references unknown rear port \"${link.rearPortId}\"`,\n path: 'frontRearPortLinks',\n });\n }\n }\n\n const hasErrors = issues.some((i) => i.severity === 'error');\n\n return {\n valid: !hasErrors,\n issues,\n portCounts: {\n front: parsedFrontCount,\n rear: parsedRearCount,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stage E: Export / Assemble\n// ---------------------------------------------------------------------------\n\nfunction stageExport(\n ingested: IngestResult,\n normalized: NormalizeResult,\n enriched: EnrichResult\n): DeviceTemplateV2 {\n const links: TemplateFrontRearPortLink[] = ingested.rawLinks\n .filter((link) => Boolean(link.frontPortId) && Boolean(link.rearPortId))\n .map((link) => ({\n frontPortId: link.frontPortId!,\n rearPortId: link.rearPortId!,\n }));\n\n const source: TemplateSource | undefined = ingested.sourceRepository\n ? {\n kind: 'netbox',\n repository: ingested.sourceRepository,\n path: ingested.sourcePath,\n }\n : undefined;\n\n return {\n templateSchemaVersion: TEMPLATE_SCHEMA_VERSION,\n id: ingested.id,\n slug: ingested.slug,\n manufacturer: ingested.manufacturer,\n model: ingested.model,\n role: enriched.role,\n mountClass: enriched.mountClass,\n uHeight: normalized.uHeight,\n width: normalized.width,\n faces: {\n front: enriched.frontFace,\n rear: enriched.rearFace,\n },\n frontRearPortLinks: links,\n images: {\n front: enriched.frontFace.imageUrl ?? null,\n rear: enriched.rearFace.imageUrl ?? null,\n },\n source,\n tags: ingested.tags.length > 0 ? ingested.tags : undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a raw NetBox-style template through the full 5-stage pipeline.\n *\n * Returns a `TemplateParseResult` containing the validated V2 template\n * (or `null` if validation failed) and a full validation report.\n *\n * @public\n */\nexport function parseNetboxTemplate(raw: RawNetboxTemplate): TemplateParseResult {\n // Stage A\n const ingested = stageIngest(raw);\n\n // Stage B\n const normalized = stageNormalize(ingested);\n\n // Stage C\n const enriched = stageEnrich(normalized);\n\n // Stage D\n const report = stageValidate(ingested, enriched);\n report.issues.push(...ingested.issues, ...normalized.issues, ...enriched.issues);\n\n if (!report.valid) {\n return { template: null, report };\n }\n\n // Stage E\n const template = stageExport(ingested, normalized, enriched);\n\n return { template, report };\n}\n\n/**\n * Count the total number of ports on a given face of a V2 template.\n * @public\n */\nexport function countTemplateFacePorts(face: TemplateFaceData): number {\n return countFacePorts(face);\n}\n\n/**\n * Validate that rendered handle counts match the template port counts.\n * Returns issues when counts diverge — used as a regression guardrail.\n *\n * @public\n */\nexport function validateRenderFidelity(\n template: DeviceTemplateV2,\n renderedFrontHandleCount: number,\n renderedRearHandleCount: number\n): TemplateValidationIssue[] {\n const issues: TemplateValidationIssue[] = [];\n const expectedFront = countFacePorts(template.faces.front);\n const expectedRear = countFacePorts(template.faces.rear);\n\n if (renderedFrontHandleCount !== expectedFront) {\n issues.push({\n severity: 'error',\n code: 'RENDER_FRONT_COUNT_MISMATCH',\n message: `Rendered front handle count (${renderedFrontHandleCount}) does not match template (${expectedFront})`,\n path: 'faces.front',\n });\n }\n if (renderedRearHandleCount !== expectedRear) {\n issues.push({\n severity: 'error',\n code: 'RENDER_REAR_COUNT_MISMATCH',\n message: `Rendered rear handle count (${renderedRearHandleCount}) does not match template (${expectedRear})`,\n path: 'faces.rear',\n });\n }\n\n return issues;\n}\n"]}