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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.css CHANGED
@@ -264,3 +264,51 @@
264
264
  background: rgba(255, 255, 255, 0.8);
265
265
  }
266
266
 
267
+ /* Coupler node styles */
268
+ .coupler-node {
269
+ transition: box-shadow 0.2s ease;
270
+ }
271
+
272
+ .coupler-node.selected {
273
+ box-shadow: 0 0 0 2px #3b82f6 !important;
274
+ }
275
+
276
+ /* Patch panel node styles */
277
+ .patch-panel-node {
278
+ transition: box-shadow 0.2s ease, border-color 0.2s ease;
279
+ }
280
+
281
+ .patch-panel-node.selected {
282
+ box-shadow: 0 0 0 2px #3b82f6 !important;
283
+ border-color: #3b82f6 !important;
284
+ }
285
+
286
+ /* Closure node styles */
287
+ .closure-node {
288
+ transition: box-shadow 0.2s ease, border-color 0.2s ease;
289
+ }
290
+
291
+ .closure-node.selected {
292
+ box-shadow: 0 0 0 2px #3b82f6 !important;
293
+ border-color: #3b82f6 !important;
294
+ }
295
+
296
+ /* Light mode adjustments */
297
+ .react-flow-light .coupler-node {
298
+ background: #f9fafb;
299
+ color: #1f2937;
300
+ border-color: #d1d5db;
301
+ }
302
+
303
+ .react-flow-light .patch-panel-node {
304
+ background: transparent !important;
305
+ color: #1f2937;
306
+ border-color: #d1d5db;
307
+ }
308
+
309
+ .react-flow-light .closure-node {
310
+ background: transparent !important;
311
+ color: #1f2937;
312
+ border-color: #d1d5db;
313
+ }
314
+
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles/index.css"],"sourcesContent":["/* Library styles for @react-networks/network-diagrams */\n\n/* Edge zIndex styles for dynamic prominence */\n.edge-prominent {\n z-index: 1000 !important;\n opacity: 1 !important;\n}\n\n.edge-dimmed {\n z-index: 500 !important;\n opacity: 0.3 !important;\n}\n\n/* Dynamic zIndex classes */\n.edge-z-1000 {\n z-index: 1000 !important;\n}\n\n.edge-z-500 {\n z-index: 500 !important;\n}\n\n/* React Flow theming */\n.react-flow-dark {\n --react-flow-background: #1a1a1a;\n --react-flow-text: #ffffff;\n --react-flow-border: #404040;\n --react-flow-controls-bg: #2d2d2d;\n --react-flow-controls-border: #404040;\n --react-flow-minimap-bg: #2d2d2d;\n --react-flow-minimap-border: #404040;\n}\n\n.react-flow-light {\n --react-flow-background: #f5f5f5;\n --react-flow-text: #1a1a1a;\n --react-flow-border: #e9ecef;\n --react-flow-controls-bg: #f8f9fa;\n --react-flow-controls-border: #e9ecef;\n --react-flow-minimap-bg: #f8f9fa;\n --react-flow-minimap-border: #e9ecef;\n}\n\n/* Apply ReactFlow theming */\n.react-flow-dark .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n.react-flow-light .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n/* Ensure canvas background is always off-white in light mode */\n.react-flow-light .react-flow__viewport {\n background-color: #f5f5f5 !important;\n}\n\n.react-flow-light .react-flow {\n background-color: #f5f5f5;\n}\n\n.react-flow-dark .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-light .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-dark .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__controls-button:hover {\n background-color: #4b5563;\n}\n\n.react-flow-light .react-flow__controls-button:hover {\n background-color: #e9ecef;\n}\n\n/* Override React Flow default handle styles for tube fiber handles */\n/* Use CSS variables set by inline styles to override React Flow defaults */\n.react-flow__handle.tube-fiber-handle {\n border: none !important;\n transform: none !important;\n background-clip: padding-box !important;\n opacity: 1 !important;\n /* Remove React Flow's default background completely */\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n /* Ensure no default React Flow styles interfere */\n box-shadow: none !important;\n}\n\n.react-flow__handle-right.tube-fiber-handle {\n right: auto !important;\n}\n\n/* More specific selector to ensure override - target all possible React Flow handle states */\n.react-flow__node .react-flow__handle.tube-fiber-handle,\n.react-flow__node .react-flow__handle.tube-fiber-handle[data-handlepos],\n.react-flow__handle.tube-fiber-handle[data-handlepos],\n.react-flow__handle.tube-fiber-handle[data-fiber-idx] {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n background-image: var(--fiber-bg-image, none) !important;\n}\n\n/* Connection animation - pulse effect when edge is first created */\n@keyframes edgeConnectPulse {\n 0% {\n opacity: 0;\n stroke-width: 1;\n }\n 50% {\n opacity: 1;\n stroke-width: 4;\n }\n 100% {\n opacity: 1;\n stroke-width: 2;\n }\n}\n\n.react-flow__edge.edge-connecting path,\n.react-flow__edge.edge-connecting .react-flow__edge-path {\n animation: edgeConnectPulse 1s ease-out;\n}\n\n/* Splice glow animation - fade in when both handles are connected */\n@keyframes spliceGlowFadeIn {\n 0% {\n opacity: 0;\n transform: translateX(-50%) scaleY(0.3);\n }\n 100% {\n opacity: 1;\n transform: translateX(-50%) scaleY(1);\n }\n}\n\n.splice-glow {\n animation: spliceGlowFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Splice text animation - fade in when both handles are connected */\n@keyframes spliceTextFadeIn {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Splice text overlay - blur and opacity for text readability */\n.splice-text-overlay {\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n}\n\n/* Dark mode overlay */\n.react-flow-dark .splice-text-overlay {\n background: rgba(0, 0, 0, 0.6);\n}\n\n/* Light mode overlay */\n.react-flow-light .splice-text-overlay {\n background: rgba(255, 255, 255, 0.7);\n}\n\n/* Splice text label - theme-aware colors */\n.splice-text-label {\n color: #fff;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8), 0 0 2px rgba(0, 0, 0, 0.6);\n}\n\n.splice-text-label.animate-in {\n animation: spliceTextFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Light mode text */\n.react-flow-light .splice-text-label {\n color: #1a1a1a;\n text-shadow: 0 1px 2px rgba(255, 255, 255, 0.9), 0 0 4px rgba(255, 255, 255, 0.7);\n}\n\n/* Remove all borders from splice nodes */\n.react-flow__node[data-type=\"splice\"],\n.react-flow__node[data-type=\"splice\"] > div {\n border: none !important;\n outline: none !important;\n}\n\n.splice-node {\n border: none !important;\n outline: none !important;\n}\n\n/* Only remove box-shadow when not selected */\n.react-flow__node[data-type=\"splice\"]:not(.selected) > div,\n.splice-node:not(.selected) {\n box-shadow: none !important;\n}\n\n/* React Networks Attribution */\n.react-networks-attribution {\n padding: 0;\n margin: 0;\n z-index: 1000;\n}\n\n.react-networks-attribution-link {\n font-size: 7px;\n color: #9ca3af;\n text-decoration: none;\n font-family: Inter, system-ui, -apple-system, sans-serif;\n transition: color 0.2s ease;\n padding: 1px 4px;\n border-radius: 2px;\n display: inline-block;\n background: rgba(0, 0, 0, 0.3);\n backdrop-filter: blur(4px);\n}\n\n.react-networks-attribution-link:hover {\n color: #e5e7eb;\n background: rgba(0, 0, 0, 0.4);\n}\n\n/* Light mode attribution */\n.react-flow-light .react-networks-attribution-link {\n color: #6b7280;\n background: rgba(255, 255, 255, 0.6);\n}\n\n.react-flow-light .react-networks-attribution-link:hover {\n color: #1a1a1a;\n background: rgba(255, 255, 255, 0.8);\n}\n\n/* Coupler node styles */\n.coupler-node {\n transition: box-shadow 0.2s ease;\n}\n\n.coupler-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n}\n\n/* Patch panel node styles */\n.patch-panel-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.patch-panel-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Closure node styles */\n.closure-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.closure-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Light mode adjustments */\n.react-flow-light .coupler-node {\n background: #f9fafb;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .patch-panel-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .closure-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -39,7 +39,7 @@ interface PortBlock {
39
39
  * Network node types supported by the diagram
40
40
  * @public
41
41
  */
42
- type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable';
42
+ type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'coupler' | 'closure';
43
43
  /**
44
44
  * Device status states
45
45
  * @public
@@ -122,6 +122,26 @@ interface NetworkNode {
122
122
  holderPosition?: number;
123
123
  /** Loss value in dB for splice nodes */
124
124
  lossDb?: number;
125
+ /** Connector type for coupler nodes */
126
+ connector?: 'SC' | 'LC';
127
+ /** Number of fibers for coupler nodes (1, 2, or 4) */
128
+ couplerFiberCount?: 1 | 2 | 4;
129
+ /** Optional port labels for left side of coupler */
130
+ portLabelsLeft?: string[];
131
+ /** Optional port labels for right side of coupler */
132
+ portLabelsRight?: string[];
133
+ /** Slot position for couplers inside panels (1-based, vertical slots aligned to right edge) */
134
+ slotPosition?: number;
135
+ /** Width override for container nodes (patch-panel, closure) */
136
+ panelWidth?: number;
137
+ /** Height override for container nodes (patch-panel, closure) */
138
+ panelHeight?: number;
139
+ /** Number of rows for container nodes (patch-panel, closure) */
140
+ rows?: number;
141
+ /** Number of columns for container nodes (patch-panel, closure) */
142
+ cols?: number;
143
+ /** Header text for container nodes */
144
+ header?: string;
125
145
  /** Additional custom properties */
126
146
  [key: string]: any;
127
147
  };
@@ -130,7 +150,7 @@ interface NetworkNode {
130
150
  * Network edge types
131
151
  * @public
132
152
  */
133
- type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step';
153
+ type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable';
134
154
  /**
135
155
  * Network edge data structure
136
156
  * @public
@@ -383,6 +403,12 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
383
403
  */
384
404
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
385
405
 
406
+ declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
407
+
408
+ declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
+
410
+ declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
+
386
412
  interface InventoryRackDTO {
387
413
  id: string | number;
388
414
  name: string;
@@ -549,6 +575,114 @@ declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosit
549
575
  y: number;
550
576
  };
551
577
 
578
+ /**
579
+ * Panel header height in pixels
580
+ */
581
+ declare const PANEL_HEADER_HEIGHT = 32;
582
+ /**
583
+ * Coupler slot height in pixels
584
+ */
585
+ declare const COUPLER_SLOT_HEIGHT_PX = 30;
586
+ /**
587
+ * Default number of couplers per panel
588
+ */
589
+ declare const COUPLERS_PER_PANEL = 24;
590
+ /**
591
+ * Default coupler width in pixels
592
+ */
593
+ declare const COUPLER_WIDTH_PX = 80;
594
+ /**
595
+ * Default panel width in pixels
596
+ */
597
+ declare const PANEL_WIDTH_PX = 400;
598
+ /**
599
+ * Default panel height in pixels
600
+ */
601
+ declare const PANEL_HEIGHT_PX = 300;
602
+ /**
603
+ * Panel border width in pixels
604
+ */
605
+ declare const PANEL_BORDER_WIDTH = 2;
606
+ /**
607
+ * Panel padding in pixels
608
+ */
609
+ declare const PANEL_PADDING = 8;
610
+ /**
611
+ * Spacing between tubes and trays in patch panels (horizontal spacing)
612
+ */
613
+ declare const PANEL_TUBE_TRAY_SPACING = 120;
614
+ /**
615
+ * Calculate coupler dimensions based on node data
616
+ */
617
+ declare function getCouplerDimensions(node: NetworkNode): {
618
+ width: number;
619
+ height: number;
620
+ };
621
+ /**
622
+ * Calculate tube dimensions based on node data
623
+ */
624
+ declare function getTubeDimensions(node: NetworkNode): {
625
+ width: number;
626
+ height: number;
627
+ };
628
+ /**
629
+ * Get tray dimensions
630
+ */
631
+ declare function getTrayDimensions(_node: NetworkNode): {
632
+ width: number;
633
+ height: number;
634
+ };
635
+ /**
636
+ * Calculate panel width based on content
637
+ */
638
+ declare function getPanelWidth(panelNode: NetworkNode): number;
639
+ /**
640
+ * Calculate panel height based on content
641
+ */
642
+ declare function getPanelHeight(panelNode: NetworkNode): number;
643
+ /**
644
+ * Get inner content width (panel width minus borders/padding)
645
+ */
646
+ declare function getInnerContentWidth(panelNode: NetworkNode): number;
647
+ /**
648
+ * Calculate coupler right X position
649
+ */
650
+ declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
651
+ /**
652
+ * Calculate slot position from Y coordinate
653
+ */
654
+ declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
655
+ /**
656
+ * Calculate Y coordinate from slot position
657
+ */
658
+ declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
659
+ /**
660
+ * Snap coupler to nearest slot position
661
+ */
662
+ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
663
+ x: number;
664
+ y: number;
665
+ }): {
666
+ x: number;
667
+ y: number;
668
+ slotPosition?: number;
669
+ };
670
+ /**
671
+ * Calculate panel dimensions based on child nodes
672
+ */
673
+ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
674
+ width: number;
675
+ height: number;
676
+ };
677
+ /**
678
+ * Calculate spacing between couplers
679
+ */
680
+ declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
681
+ /**
682
+ * Calculate coupler slot spacing
683
+ */
684
+ declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
685
+
552
686
  /**
553
687
  * Configuration options for building nodes from rack schema
554
688
  */
@@ -812,7 +946,7 @@ interface ReplaceEdgeOptions {
812
946
  /** Connection parameters for the new edge */
813
947
  connection: Connection;
814
948
  /** Type of edge to create */
815
- edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';
949
+ edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable';
816
950
  /** Function to calculate zIndex for the edge */
817
951
  selectEdgeZIndex: (edge: NetworkEdge) => number;
818
952
  /** Whether to find edge by source or target */
@@ -862,4 +996,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
862
996
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
863
997
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
864
998
 
865
- export { CableNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, POWER_CONNECTORS, type Port, type PortBlock, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateDevicePositionFromU, calculateSplicePositionFromNumber, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getDeviceConnectorType, getFiberColor, getPDUPortType, getPowerPortStyle, getRackBounds, getStatusColor, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };
999
+ export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, PANEL_BORDER_WIDTH, PANEL_HEADER_HEIGHT, PANEL_HEIGHT_PX, PANEL_PADDING, PANEL_TUBE_TRAY_SPACING, PANEL_WIDTH_PX, POWER_CONNECTORS, PatchPanelNode, type Port, type PortBlock, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateYFromSlotPosition, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDeviceConnectorType, getFiberColor, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getStatusColor, getTrayDimensions, getTubeDimensions, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };
package/dist/index.d.ts CHANGED
@@ -39,7 +39,7 @@ interface PortBlock {
39
39
  * Network node types supported by the diagram
40
40
  * @public
41
41
  */
42
- type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable';
42
+ type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'coupler' | 'closure';
43
43
  /**
44
44
  * Device status states
45
45
  * @public
@@ -122,6 +122,26 @@ interface NetworkNode {
122
122
  holderPosition?: number;
123
123
  /** Loss value in dB for splice nodes */
124
124
  lossDb?: number;
125
+ /** Connector type for coupler nodes */
126
+ connector?: 'SC' | 'LC';
127
+ /** Number of fibers for coupler nodes (1, 2, or 4) */
128
+ couplerFiberCount?: 1 | 2 | 4;
129
+ /** Optional port labels for left side of coupler */
130
+ portLabelsLeft?: string[];
131
+ /** Optional port labels for right side of coupler */
132
+ portLabelsRight?: string[];
133
+ /** Slot position for couplers inside panels (1-based, vertical slots aligned to right edge) */
134
+ slotPosition?: number;
135
+ /** Width override for container nodes (patch-panel, closure) */
136
+ panelWidth?: number;
137
+ /** Height override for container nodes (patch-panel, closure) */
138
+ panelHeight?: number;
139
+ /** Number of rows for container nodes (patch-panel, closure) */
140
+ rows?: number;
141
+ /** Number of columns for container nodes (patch-panel, closure) */
142
+ cols?: number;
143
+ /** Header text for container nodes */
144
+ header?: string;
125
145
  /** Additional custom properties */
126
146
  [key: string]: any;
127
147
  };
@@ -130,7 +150,7 @@ interface NetworkNode {
130
150
  * Network edge types
131
151
  * @public
132
152
  */
133
- type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step';
153
+ type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable';
134
154
  /**
135
155
  * Network edge data structure
136
156
  * @public
@@ -383,6 +403,12 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
383
403
  */
384
404
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
385
405
 
406
+ declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
407
+
408
+ declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
+
410
+ declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
+
386
412
  interface InventoryRackDTO {
387
413
  id: string | number;
388
414
  name: string;
@@ -549,6 +575,114 @@ declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosit
549
575
  y: number;
550
576
  };
551
577
 
578
+ /**
579
+ * Panel header height in pixels
580
+ */
581
+ declare const PANEL_HEADER_HEIGHT = 32;
582
+ /**
583
+ * Coupler slot height in pixels
584
+ */
585
+ declare const COUPLER_SLOT_HEIGHT_PX = 30;
586
+ /**
587
+ * Default number of couplers per panel
588
+ */
589
+ declare const COUPLERS_PER_PANEL = 24;
590
+ /**
591
+ * Default coupler width in pixels
592
+ */
593
+ declare const COUPLER_WIDTH_PX = 80;
594
+ /**
595
+ * Default panel width in pixels
596
+ */
597
+ declare const PANEL_WIDTH_PX = 400;
598
+ /**
599
+ * Default panel height in pixels
600
+ */
601
+ declare const PANEL_HEIGHT_PX = 300;
602
+ /**
603
+ * Panel border width in pixels
604
+ */
605
+ declare const PANEL_BORDER_WIDTH = 2;
606
+ /**
607
+ * Panel padding in pixels
608
+ */
609
+ declare const PANEL_PADDING = 8;
610
+ /**
611
+ * Spacing between tubes and trays in patch panels (horizontal spacing)
612
+ */
613
+ declare const PANEL_TUBE_TRAY_SPACING = 120;
614
+ /**
615
+ * Calculate coupler dimensions based on node data
616
+ */
617
+ declare function getCouplerDimensions(node: NetworkNode): {
618
+ width: number;
619
+ height: number;
620
+ };
621
+ /**
622
+ * Calculate tube dimensions based on node data
623
+ */
624
+ declare function getTubeDimensions(node: NetworkNode): {
625
+ width: number;
626
+ height: number;
627
+ };
628
+ /**
629
+ * Get tray dimensions
630
+ */
631
+ declare function getTrayDimensions(_node: NetworkNode): {
632
+ width: number;
633
+ height: number;
634
+ };
635
+ /**
636
+ * Calculate panel width based on content
637
+ */
638
+ declare function getPanelWidth(panelNode: NetworkNode): number;
639
+ /**
640
+ * Calculate panel height based on content
641
+ */
642
+ declare function getPanelHeight(panelNode: NetworkNode): number;
643
+ /**
644
+ * Get inner content width (panel width minus borders/padding)
645
+ */
646
+ declare function getInnerContentWidth(panelNode: NetworkNode): number;
647
+ /**
648
+ * Calculate coupler right X position
649
+ */
650
+ declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
651
+ /**
652
+ * Calculate slot position from Y coordinate
653
+ */
654
+ declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
655
+ /**
656
+ * Calculate Y coordinate from slot position
657
+ */
658
+ declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
659
+ /**
660
+ * Snap coupler to nearest slot position
661
+ */
662
+ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
663
+ x: number;
664
+ y: number;
665
+ }): {
666
+ x: number;
667
+ y: number;
668
+ slotPosition?: number;
669
+ };
670
+ /**
671
+ * Calculate panel dimensions based on child nodes
672
+ */
673
+ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
674
+ width: number;
675
+ height: number;
676
+ };
677
+ /**
678
+ * Calculate spacing between couplers
679
+ */
680
+ declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
681
+ /**
682
+ * Calculate coupler slot spacing
683
+ */
684
+ declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
685
+
552
686
  /**
553
687
  * Configuration options for building nodes from rack schema
554
688
  */
@@ -812,7 +946,7 @@ interface ReplaceEdgeOptions {
812
946
  /** Connection parameters for the new edge */
813
947
  connection: Connection;
814
948
  /** Type of edge to create */
815
- edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';
949
+ edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable';
816
950
  /** Function to calculate zIndex for the edge */
817
951
  selectEdgeZIndex: (edge: NetworkEdge) => number;
818
952
  /** Whether to find edge by source or target */
@@ -862,4 +996,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
862
996
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
863
997
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
864
998
 
865
- export { CableNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, POWER_CONNECTORS, type Port, type PortBlock, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateDevicePositionFromU, calculateSplicePositionFromNumber, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getDeviceConnectorType, getFiberColor, getPDUPortType, getPowerPortStyle, getRackBounds, getStatusColor, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };
999
+ export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, PANEL_BORDER_WIDTH, PANEL_HEADER_HEIGHT, PANEL_HEIGHT_PX, PANEL_PADDING, PANEL_TUBE_TRAY_SPACING, PANEL_WIDTH_PX, POWER_CONNECTORS, PatchPanelNode, type Port, type PortBlock, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateYFromSlotPosition, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDeviceConnectorType, getFiberColor, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getStatusColor, getTrayDimensions, getTubeDimensions, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };