@mp70/react-networks 0.1.5-alpha → 0.1.7-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
@@ -336,6 +356,8 @@ interface NetworkDiagramProps {
336
356
  allowReconnectExisting?: boolean;
337
357
  /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */
338
358
  useSmoothstepEdgesForTubes?: boolean;
359
+ /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */
360
+ connectOnClick?: boolean;
339
361
  }
340
362
 
341
363
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
@@ -383,6 +405,12 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
383
405
  */
384
406
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
385
407
 
408
+ declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
+
410
+ declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
+
412
+ declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
413
+
386
414
  interface InventoryRackDTO {
387
415
  id: string | number;
388
416
  name: string;
@@ -549,6 +577,114 @@ declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosit
549
577
  y: number;
550
578
  };
551
579
 
580
+ /**
581
+ * Panel header height in pixels
582
+ */
583
+ declare const PANEL_HEADER_HEIGHT = 32;
584
+ /**
585
+ * Coupler slot height in pixels
586
+ */
587
+ declare const COUPLER_SLOT_HEIGHT_PX = 30;
588
+ /**
589
+ * Default number of couplers per panel
590
+ */
591
+ declare const COUPLERS_PER_PANEL = 24;
592
+ /**
593
+ * Default coupler width in pixels
594
+ */
595
+ declare const COUPLER_WIDTH_PX = 80;
596
+ /**
597
+ * Default panel width in pixels
598
+ */
599
+ declare const PANEL_WIDTH_PX = 400;
600
+ /**
601
+ * Default panel height in pixels
602
+ */
603
+ declare const PANEL_HEIGHT_PX = 300;
604
+ /**
605
+ * Panel border width in pixels
606
+ */
607
+ declare const PANEL_BORDER_WIDTH = 2;
608
+ /**
609
+ * Panel padding in pixels
610
+ */
611
+ declare const PANEL_PADDING = 8;
612
+ /**
613
+ * Spacing between tubes and trays in patch panels (horizontal spacing)
614
+ */
615
+ declare const PANEL_TUBE_TRAY_SPACING = 120;
616
+ /**
617
+ * Calculate coupler dimensions based on node data
618
+ */
619
+ declare function getCouplerDimensions(node: NetworkNode): {
620
+ width: number;
621
+ height: number;
622
+ };
623
+ /**
624
+ * Calculate tube dimensions based on node data
625
+ */
626
+ declare function getTubeDimensions(node: NetworkNode): {
627
+ width: number;
628
+ height: number;
629
+ };
630
+ /**
631
+ * Get tray dimensions
632
+ */
633
+ declare function getTrayDimensions(_node: NetworkNode): {
634
+ width: number;
635
+ height: number;
636
+ };
637
+ /**
638
+ * Calculate panel width based on content
639
+ */
640
+ declare function getPanelWidth(panelNode: NetworkNode): number;
641
+ /**
642
+ * Calculate panel height based on content
643
+ */
644
+ declare function getPanelHeight(panelNode: NetworkNode): number;
645
+ /**
646
+ * Get inner content width (panel width minus borders/padding)
647
+ */
648
+ declare function getInnerContentWidth(panelNode: NetworkNode): number;
649
+ /**
650
+ * Calculate coupler right X position
651
+ */
652
+ declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
653
+ /**
654
+ * Calculate slot position from Y coordinate
655
+ */
656
+ declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
657
+ /**
658
+ * Calculate Y coordinate from slot position
659
+ */
660
+ declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
661
+ /**
662
+ * Snap coupler to nearest slot position
663
+ */
664
+ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
665
+ x: number;
666
+ y: number;
667
+ }): {
668
+ x: number;
669
+ y: number;
670
+ slotPosition?: number;
671
+ };
672
+ /**
673
+ * Calculate panel dimensions based on child nodes
674
+ */
675
+ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
676
+ width: number;
677
+ height: number;
678
+ };
679
+ /**
680
+ * Calculate spacing between couplers
681
+ */
682
+ declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
683
+ /**
684
+ * Calculate coupler slot spacing
685
+ */
686
+ declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
687
+
552
688
  /**
553
689
  * Configuration options for building nodes from rack schema
554
690
  */
@@ -812,7 +948,7 @@ interface ReplaceEdgeOptions {
812
948
  /** Connection parameters for the new edge */
813
949
  connection: Connection;
814
950
  /** Type of edge to create */
815
- edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';
951
+ edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable';
816
952
  /** Function to calculate zIndex for the edge */
817
953
  selectEdgeZIndex: (edge: NetworkEdge) => number;
818
954
  /** Whether to find edge by source or target */
@@ -862,4 +998,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
862
998
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
863
999
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
864
1000
 
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 };
1001
+ 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
@@ -336,6 +356,8 @@ interface NetworkDiagramProps {
336
356
  allowReconnectExisting?: boolean;
337
357
  /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */
338
358
  useSmoothstepEdgesForTubes?: boolean;
359
+ /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */
360
+ connectOnClick?: boolean;
339
361
  }
340
362
 
341
363
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
@@ -383,6 +405,12 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
383
405
  */
384
406
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
385
407
 
408
+ declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
+
410
+ declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
+
412
+ declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
413
+
386
414
  interface InventoryRackDTO {
387
415
  id: string | number;
388
416
  name: string;
@@ -549,6 +577,114 @@ declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosit
549
577
  y: number;
550
578
  };
551
579
 
580
+ /**
581
+ * Panel header height in pixels
582
+ */
583
+ declare const PANEL_HEADER_HEIGHT = 32;
584
+ /**
585
+ * Coupler slot height in pixels
586
+ */
587
+ declare const COUPLER_SLOT_HEIGHT_PX = 30;
588
+ /**
589
+ * Default number of couplers per panel
590
+ */
591
+ declare const COUPLERS_PER_PANEL = 24;
592
+ /**
593
+ * Default coupler width in pixels
594
+ */
595
+ declare const COUPLER_WIDTH_PX = 80;
596
+ /**
597
+ * Default panel width in pixels
598
+ */
599
+ declare const PANEL_WIDTH_PX = 400;
600
+ /**
601
+ * Default panel height in pixels
602
+ */
603
+ declare const PANEL_HEIGHT_PX = 300;
604
+ /**
605
+ * Panel border width in pixels
606
+ */
607
+ declare const PANEL_BORDER_WIDTH = 2;
608
+ /**
609
+ * Panel padding in pixels
610
+ */
611
+ declare const PANEL_PADDING = 8;
612
+ /**
613
+ * Spacing between tubes and trays in patch panels (horizontal spacing)
614
+ */
615
+ declare const PANEL_TUBE_TRAY_SPACING = 120;
616
+ /**
617
+ * Calculate coupler dimensions based on node data
618
+ */
619
+ declare function getCouplerDimensions(node: NetworkNode): {
620
+ width: number;
621
+ height: number;
622
+ };
623
+ /**
624
+ * Calculate tube dimensions based on node data
625
+ */
626
+ declare function getTubeDimensions(node: NetworkNode): {
627
+ width: number;
628
+ height: number;
629
+ };
630
+ /**
631
+ * Get tray dimensions
632
+ */
633
+ declare function getTrayDimensions(_node: NetworkNode): {
634
+ width: number;
635
+ height: number;
636
+ };
637
+ /**
638
+ * Calculate panel width based on content
639
+ */
640
+ declare function getPanelWidth(panelNode: NetworkNode): number;
641
+ /**
642
+ * Calculate panel height based on content
643
+ */
644
+ declare function getPanelHeight(panelNode: NetworkNode): number;
645
+ /**
646
+ * Get inner content width (panel width minus borders/padding)
647
+ */
648
+ declare function getInnerContentWidth(panelNode: NetworkNode): number;
649
+ /**
650
+ * Calculate coupler right X position
651
+ */
652
+ declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
653
+ /**
654
+ * Calculate slot position from Y coordinate
655
+ */
656
+ declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
657
+ /**
658
+ * Calculate Y coordinate from slot position
659
+ */
660
+ declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
661
+ /**
662
+ * Snap coupler to nearest slot position
663
+ */
664
+ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
665
+ x: number;
666
+ y: number;
667
+ }): {
668
+ x: number;
669
+ y: number;
670
+ slotPosition?: number;
671
+ };
672
+ /**
673
+ * Calculate panel dimensions based on child nodes
674
+ */
675
+ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
676
+ width: number;
677
+ height: number;
678
+ };
679
+ /**
680
+ * Calculate spacing between couplers
681
+ */
682
+ declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
683
+ /**
684
+ * Calculate coupler slot spacing
685
+ */
686
+ declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
687
+
552
688
  /**
553
689
  * Configuration options for building nodes from rack schema
554
690
  */
@@ -812,7 +948,7 @@ interface ReplaceEdgeOptions {
812
948
  /** Connection parameters for the new edge */
813
949
  connection: Connection;
814
950
  /** Type of edge to create */
815
- edgeType: 'power' | 'fiber' | 'step' | 'smoothstep';
951
+ edgeType: 'power' | 'fiber' | 'step' | 'smoothstep' | 'thick-cable';
816
952
  /** Function to calculate zIndex for the edge */
817
953
  selectEdgeZIndex: (edge: NetworkEdge) => number;
818
954
  /** Whether to find edge by source or target */
@@ -862,4 +998,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
862
998
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
863
999
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
864
1000
 
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 };
1001
+ 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 };