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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,10 +1,11 @@
1
- import React$1 from 'react';
2
- import { NodeProps, EdgeProps, Edge, Connection } from 'reactflow';
1
+ import React$1, { Component, ReactNode, ErrorInfo } from 'react';
2
+ import { NodeTypes, EdgeTypes, Connection, Edge, ConnectionMode, FitViewOptions, NodeProps, EdgeProps } from 'reactflow';
3
3
 
4
4
  /**
5
5
  * Rack device width configuration
6
6
  * @public
7
7
  */
8
+
8
9
  declare enum Width {
9
10
  /** Full width device (19" rack width) */
10
11
  FULL = "full",
@@ -15,13 +16,18 @@ declare enum Width {
15
16
  * Port configuration for network devices
16
17
  * @public
17
18
  */
19
+ /**
20
+ * Port type enumeration
21
+ * @public
22
+ */
23
+ type PortType = 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';
18
24
  interface Port {
19
25
  /** Display label for the port */
20
26
  label: string;
21
27
  /** Whether the port is currently connected */
22
28
  connected: boolean;
23
29
  /** Type of port for styling and validation */
24
- type?: 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';
30
+ type?: PortType;
25
31
  /** Cable type for connection validation */
26
32
  cableType?: 'smf' | 'cat6' | 'om3' | 'om4' | 'om5' | 'cat5e' | 'cat6a' | 'cat7' | 'fiber' | 'ethernet';
27
33
  }
@@ -39,7 +45,7 @@ interface PortBlock {
39
45
  * Network node types supported by the diagram
40
46
  * @public
41
47
  */
42
- type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'coupler' | 'closure';
48
+ type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'multi-tube-cable' | 'coupler' | 'closure' | 'fibre-split' | 'fibre-flow-cable' | 'fibre-flow-closure';
43
49
  /**
44
50
  * Device status states
45
51
  * @public
@@ -110,6 +116,16 @@ interface NetworkNode {
110
116
  rearPorts?: PortBlock[];
111
117
  /** Power port side for rear view */
112
118
  powerSide?: PowerSide;
119
+ /** Optional front image URL for device background */
120
+ frontImageUrl?: string;
121
+ /** Optional rear image URL for device background */
122
+ rearImageUrl?: string;
123
+ /** Optional background sizing for device images */
124
+ imageFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
125
+ /** Optional background position for device images */
126
+ imagePosition?: string;
127
+ /** Optional background repeat for device images */
128
+ imageRepeat?: 'no-repeat' | 'repeat' | 'repeat-x' | 'repeat-y';
113
129
  /** Vertical PDU height in centimeters */
114
130
  heightCm?: number;
115
131
  /** Number of AC power ports */
@@ -136,12 +152,20 @@ interface NetworkNode {
136
152
  panelWidth?: number;
137
153
  /** Height override for container nodes (patch-panel, closure) */
138
154
  panelHeight?: number;
155
+ /** Optional rack width in pixels (for rack nodes, default: 300px) */
156
+ rackWidthPx?: number;
139
157
  /** Number of rows for container nodes (patch-panel, closure) */
140
158
  rows?: number;
141
159
  /** Number of columns for container nodes (patch-panel, closure) */
142
160
  cols?: number;
143
161
  /** Header text for container nodes */
144
162
  header?: string;
163
+ /** Type of fibre splitter: 'splitter' or 'WDM' (default: 'splitter') */
164
+ splitterType?: 'splitter' | 'WDM';
165
+ /** Number of input fibers on the left (1 or 2, default: 1) */
166
+ inputCount?: number;
167
+ /** Number of output fibers on the right (1-64, default: 8) */
168
+ outputCount?: number;
145
169
  /** Additional custom properties */
146
170
  [key: string]: any;
147
171
  };
@@ -150,7 +174,7 @@ interface NetworkNode {
150
174
  * Network edge types
151
175
  * @public
152
176
  */
153
- type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable';
177
+ type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable' | 'fibre-flow' | 'fibre-flow-link';
154
178
  /**
155
179
  * Network edge data structure
156
180
  * @public
@@ -178,6 +202,18 @@ interface NetworkEdge {
178
202
  color?: string;
179
203
  /** Edge kind for styling/validation */
180
204
  kind?: 'fiber' | 'power' | 'network';
205
+ /** Whether this edge represents a ribbon fiber connection */
206
+ isRibbon?: boolean;
207
+ /** Array of fiber IDs for ribbon mode (6-12 fibers) */
208
+ ribbonFiberIds?: number[];
209
+ /** Highlight edge with a pulsing stroke */
210
+ highlight?: boolean;
211
+ /** Override highlight color (defaults to edge color) */
212
+ highlightColor?: string;
213
+ /** Override highlight max stroke width */
214
+ highlightWidth?: number;
215
+ /** Optional tag for grouping edges in demos */
216
+ traceTag?: string;
181
217
  /** Additional custom properties */
182
218
  [key: string]: any;
183
219
  };
@@ -209,6 +245,8 @@ interface RackConfig {
209
245
  customHeaderText?: string;
210
246
  /** Devices mounted in the rack */
211
247
  devices: RackDevice[];
248
+ /** Optional rack width in pixels (default: 300px which represents standard 48.26cm/19" rack) */
249
+ rackWidthPx?: number;
212
250
  }
213
251
  /**
214
252
  * Device mounted in a rack
@@ -235,6 +273,16 @@ interface RackDevice {
235
273
  rearPorts?: PortBlock[];
236
274
  /** Power port side for rear view */
237
275
  powerSide?: PowerSide;
276
+ /** Optional front image URL for device background */
277
+ frontImageUrl?: string;
278
+ /** Optional rear image URL for device background */
279
+ rearImageUrl?: string;
280
+ /** Optional background sizing for device images */
281
+ imageFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
282
+ /** Optional background position for device images */
283
+ imagePosition?: string;
284
+ /** Optional background repeat for device images */
285
+ imageRepeat?: 'no-repeat' | 'repeat' | 'repeat-x' | 'repeat-y';
238
286
  /** Connected device IDs */
239
287
  connections?: string[];
240
288
  }
@@ -279,6 +327,10 @@ interface SpliceConfig {
279
327
  holder: number;
280
328
  /** Loss value in dB */
281
329
  lossDb?: number;
330
+ /** Splice mode: 'single' for individual fiber, 'ribbon' for ribbon splices */
331
+ mode?: 'single' | 'ribbon';
332
+ /** For ribbon mode: array of fiber IDs (6-12) in the ribbon */
333
+ ribbonFiberIds?: number[];
282
334
  }
283
335
  /**
284
336
  * Splice tray configuration structure
@@ -322,6 +374,18 @@ interface NetworkDiagramProps {
322
374
  onNodeClick?: (node: NetworkNode | null) => void;
323
375
  /** Callback when an edge is clicked */
324
376
  onEdgeClick?: (edge: NetworkEdge) => void;
377
+ /** Custom React Flow node types to merge with defaults */
378
+ nodeTypes?: NodeTypes;
379
+ /** Custom React Flow edge types to merge with defaults */
380
+ edgeTypes?: EdgeTypes;
381
+ /** Optional onConnect override (React Flow connection handler) */
382
+ onConnect?: (connection: Connection) => void;
383
+ /** Optional onEdgeUpdate override */
384
+ onEdgeUpdate?: (oldEdge: Edge, newConnection: Connection) => void;
385
+ /** Optional isValidConnection override */
386
+ isValidConnection?: (connection: Connection) => boolean;
387
+ /** Optional connection mode override */
388
+ connectionMode?: ConnectionMode;
325
389
  /** Callback when device view changes */
326
390
  onViewChange?: (nodeId: string, view: DeviceView) => void;
327
391
  /** Callback when rack face changes */
@@ -343,6 +407,9 @@ interface NetworkDiagramProps {
343
407
  setNodes: (nodes: any[]) => void;
344
408
  setEdges: (edges: any[]) => void;
345
409
  toImage: (options?: any) => Promise<string>;
410
+ getNodes: () => any[];
411
+ getEdges: () => any[];
412
+ fitView: (options?: any) => void;
346
413
  }) => void;
347
414
  /** Show download button */
348
415
  showDownloadButton?: boolean;
@@ -352,31 +419,175 @@ interface NetworkDiagramProps {
352
419
  downloadButtonText?: string;
353
420
  /** Download button styling options */
354
421
  downloadButtonStyle?: React.CSSProperties;
355
- /** Allow reconnecting existing edges from either end */
356
- allowReconnectExisting?: boolean;
357
422
  /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */
358
423
  useSmoothstepEdgesForTubes?: boolean;
359
424
  /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */
360
425
  connectOnClick?: boolean;
426
+ /** Disable panning on drag. Default is false. */
427
+ panOnDrag?: boolean;
428
+ /** Disable panning on scroll. Default is true. */
429
+ panOnScroll?: boolean;
430
+ /** Disable zooming on scroll. Default is true. */
431
+ zoomOnScroll?: boolean;
432
+ /** Optional fitView options passed to React Flow */
433
+ fitViewOptions?: FitViewOptions;
361
434
  }
362
435
 
436
+ /**
437
+ * Main component for rendering interactive network diagrams.
438
+ *
439
+ * The NetworkDiagram component provides a complete solution for visualizing
440
+ * network infrastructure including racks, devices, fiber connections, and power distribution.
441
+ *
442
+ * @example
443
+ * ```tsx
444
+ * import { NetworkDiagram, NetworkNode, NetworkEdge } from '@mp70/react-networks';
445
+ *
446
+ * const nodes: NetworkNode[] = [
447
+ * {
448
+ * id: 'rack-1',
449
+ * type: 'rack',
450
+ * position: { x: 100, y: 100 },
451
+ * data: { label: 'Main Rack', uHeight: 42 }
452
+ * }
453
+ * ];
454
+ *
455
+ * <NetworkDiagram nodes={nodes} edges={[]} />
456
+ * ```
457
+ *
458
+ * @public
459
+ */
363
460
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
364
461
 
462
+ interface DiagramErrorBoundaryProps {
463
+ /** Content to render when an error is caught */
464
+ children: ReactNode;
465
+ /** Optional fallback UI when an error occurs (default: simple message) */
466
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
467
+ /** Optional callback when an error is caught (e.g. for logging) */
468
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
469
+ }
470
+ interface State {
471
+ error: Error | null;
472
+ }
473
+ /**
474
+ * Error boundary that catches errors in the diagram tree (e.g. React Flow,
475
+ * custom nodes) and renders a fallback instead of crashing the whole app.
476
+ * Wrap &lt;NetworkDiagram&gt; (or the diagram subtree) with this for production.
477
+ *
478
+ * @example
479
+ * ```tsx
480
+ * <DiagramErrorBoundary
481
+ * fallback={(error, reset) => (
482
+ * <div>
483
+ * <p>Diagram failed: {error.message}</p>
484
+ * <button onClick={reset}>Try again</button>
485
+ * </div>
486
+ * )}
487
+ * onError={(err, info) => logToService(err, info)}
488
+ * >
489
+ * <NetworkDiagram nodes={nodes} edges={edges} />
490
+ * </DiagramErrorBoundary>
491
+ * ```
492
+ */
493
+ declare class DiagramErrorBoundary extends Component<DiagramErrorBoundaryProps, State> {
494
+ state: State;
495
+ static getDerivedStateFromError(error: Error): State;
496
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
497
+ reset: () => void;
498
+ render(): ReactNode;
499
+ }
500
+
365
501
  interface RackNodeProps extends NodeProps<NetworkNode['data']> {
366
502
  onViewChange?: (nodeId: string, view: 'front' | 'rear') => void;
367
503
  onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void;
368
504
  isDragOver?: boolean;
369
505
  }
506
+ /**
507
+ * Rack visualization component with U positioning support.
508
+ *
509
+ * Displays a 19" rack with configurable height, front/rear view switching,
510
+ * and support for mounting devices at specific U positions.
511
+ *
512
+ * @example
513
+ * ```tsx
514
+ * {
515
+ * id: 'rack-1',
516
+ * type: 'rack',
517
+ * position: { x: 100, y: 100 },
518
+ * data: {
519
+ * label: 'Main Rack',
520
+ * uHeight: 42,
521
+ * status: 'active'
522
+ * }
523
+ * }
524
+ * ```
525
+ *
526
+ * @public
527
+ */
370
528
  declare const RackNode: React$1.FC<RackNodeProps>;
371
529
 
372
530
  declare const FiberNode: React$1.FC<NodeProps<NetworkNode['data']>>;
373
531
 
532
+ /**
533
+ * Fiber edge component for connecting fiber ports between nodes.
534
+ *
535
+ * Supports both single fiber connections with color coding and ribbon fiber
536
+ * connections (6-12 fibers) with parallel stripe visualization.
537
+ *
538
+ * @example
539
+ * ```tsx
540
+ * {
541
+ * id: 'edge-1',
542
+ * source: 'node-1',
543
+ * target: 'node-2',
544
+ * sourceHandle: 'fiber-1',
545
+ * targetHandle: 'fiber-2',
546
+ * type: 'fiber',
547
+ * data: {
548
+ * kind: 'fiber',
549
+ * ribbonFiberIds: [1, 2, 3, 4, 5, 6] // For ribbon mode
550
+ * }
551
+ * }
552
+ * ```
553
+ *
554
+ * @public
555
+ */
374
556
  declare const FiberEdge: React$1.FC<EdgeProps<NetworkEdge['data']> & {
375
557
  className?: string;
376
558
  }>;
377
559
 
378
560
  declare const PowerEdge: React$1.FC<EdgeProps>;
379
561
 
562
+ /**
563
+ * Device visualization component with port management.
564
+ *
565
+ * Represents a device that can be placed in a rack. Supports port configuration,
566
+ * U positioning, front/rear views, and various device types (servers, switches, routers, etc.).
567
+ *
568
+ * @example
569
+ * ```tsx
570
+ * {
571
+ * id: 'server-1',
572
+ * type: 'device',
573
+ * position: { x: 120, y: 150 },
574
+ * parentId: 'rack-1',
575
+ * data: {
576
+ * label: 'Web Server',
577
+ * deviceType: 'server',
578
+ * uPosition: 1,
579
+ * ports: [{
580
+ * name: 'Network Ports',
581
+ * ports: [
582
+ * { label: 'eth0', connected: true, type: 'ethernet' }
583
+ * ]
584
+ * }]
585
+ * }
586
+ * }
587
+ * ```
588
+ *
589
+ * @public
590
+ */
380
591
  declare const DeviceNode: React$1.FC<NodeProps<NetworkNode['data']>>;
381
592
 
382
593
  declare const VerticalPDU: React$1.FC<NodeProps<NetworkNode['data']>>;
@@ -399,18 +610,133 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
399
610
 
400
611
  /**
401
612
  * CableNode
402
- * - Visually mirrors TubeNode but represents an entire cable
403
- * - Each colored handle corresponds to a tube within the cable
613
+ * - Represents a multi-fiber cable (1-24 fibers)
614
+ * - Each colored handle corresponds to a single fiber
404
615
  * - Displays cable summary text (fiber count + cable identifier)
405
616
  */
406
617
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
407
618
 
619
+ /**
620
+ * MultiTubeCableNode
621
+ * - Represents a multi-tube cable (1-24 tubes)
622
+ * - Each colored handle corresponds to a tube within the cable
623
+ * - Displays cable summary text (fiber count + cable identifier)
624
+ */
625
+ declare const MultiTubeCableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
626
+
408
627
  declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
628
 
410
629
  declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
630
 
412
631
  declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
413
632
 
633
+ /**
634
+ * FibreSplitNode component for rendering fiber splitters and WDM devices
635
+ * Uses a trapezoid shape pointing right (narrow input on left, wider outputs on right)
636
+ *
637
+ * @public
638
+ */
639
+ declare const FibreSplitNode: React$1.FC<NodeProps<NetworkNode['data']>>;
640
+
641
+ type FibreFlowCableKind = 'simple' | 'tube';
642
+ interface FibreFlowEndpoint {
643
+ tube?: number;
644
+ fiber: number;
645
+ }
646
+ interface FibreFlowSplice {
647
+ id: string;
648
+ from: FibreFlowEndpoint;
649
+ to: FibreFlowEndpoint;
650
+ lossDb?: number;
651
+ circuitId?: string;
652
+ label?: string;
653
+ color?: string;
654
+ }
655
+ interface FibreFlowCable {
656
+ id: string;
657
+ label: string;
658
+ kind?: FibreFlowCableKind;
659
+ fiberCount?: number;
660
+ tubeCount?: number;
661
+ fibersPerTube?: number;
662
+ tubeStartIndex?: number;
663
+ fiberStartIndex?: number;
664
+ tubeColorMap?: Record<number, string>;
665
+ jacketColor?: string;
666
+ distanceLabel?: string;
667
+ distanceMeters?: number;
668
+ }
669
+ interface FibreFlowClosure {
670
+ id: string;
671
+ chamberId?: string;
672
+ leftCable: FibreFlowCable;
673
+ rightCable: FibreFlowCable;
674
+ splices: FibreFlowSplice[];
675
+ }
676
+ interface FibreFlowCircuit {
677
+ id: string;
678
+ label: string;
679
+ color?: string;
680
+ }
681
+
682
+ type FibreFlowLayoutDirection = 'horizontal' | 'vertical';
683
+ type FibreFlowColorMode = 'dark' | 'light';
684
+ interface FibreFlowMapProps {
685
+ closures: FibreFlowClosure[];
686
+ circuits?: FibreFlowCircuit[];
687
+ highlightedCircuitId?: string;
688
+ layout?: FibreFlowLayoutDirection;
689
+ rowHeight?: number;
690
+ tubeGap?: number;
691
+ closureGap?: number;
692
+ cableColumnWidth?: number;
693
+ spliceAreaWidth?: number;
694
+ showTubeLabels?: boolean;
695
+ showFiberNumbers?: boolean;
696
+ colorMode?: FibreFlowColorMode;
697
+ showCircuitId?: boolean;
698
+ className?: string;
699
+ style?: React$1.CSSProperties;
700
+ panOnDrag?: boolean;
701
+ panOnScroll?: boolean;
702
+ zoomOnScroll?: boolean;
703
+ }
704
+ declare const FibreFlowMap: React$1.FC<FibreFlowMapProps>;
705
+
706
+ interface FibreFlowRow {
707
+ key: string;
708
+ tubeIndex?: number;
709
+ fiberIndex: number;
710
+ y: number;
711
+ color: string;
712
+ striped: boolean;
713
+ backgroundImage?: string;
714
+ }
715
+ interface FibreFlowTubeLabel {
716
+ tubeIndex: number;
717
+ y: number;
718
+ label: string;
719
+ color: string;
720
+ }
721
+ interface FibreFlowCableLayout {
722
+ rows: FibreFlowRow[];
723
+ tubeLabels: FibreFlowTubeLabel[];
724
+ height: number;
725
+ }
726
+
727
+ interface FibreCableWithTubesExpandedProps {
728
+ cable: FibreFlowCable;
729
+ side: 'left' | 'right';
730
+ rowHeight?: number;
731
+ tubeGap?: number;
732
+ columnWidth?: number;
733
+ layout?: FibreFlowCableLayout;
734
+ showTubeLabels?: boolean;
735
+ showFiberNumbers?: boolean;
736
+ showCableLabel?: boolean;
737
+ }
738
+ declare const FibreCableWithTubesExpanded: React$1.FC<FibreCableWithTubesExpandedProps>;
739
+
414
740
  interface InventoryRackDTO {
415
741
  id: string | number;
416
742
  name: string;
@@ -571,6 +897,8 @@ declare const snapToSplicePosition: (splice: NetworkNode, tray: NetworkNode, new
571
897
  declare const findNextAvailableHolderPosition: (tray: NetworkNode, splice: NetworkNode, allNodes: NetworkNode[], startFrom?: number) => number;
572
898
  /**
573
899
  * Calculate splice position based on holder number within a tray
900
+ * Note: This function doesn't have access to splice data, so it uses single mode spacing
901
+ * For ribbon splices, use calculateSplicePositionFromNumberWithData instead
574
902
  */
575
903
  declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosition: number) => {
576
904
  x: number;
@@ -615,6 +943,17 @@ declare const PANEL_PADDING = 8;
615
943
  declare const PANEL_TUBE_TRAY_SPACING = 120;
616
944
  /**
617
945
  * Calculate coupler dimensions based on node data
946
+ *
947
+ * @param node - The coupler node with optional couplerFiberCount in data
948
+ * @returns Object with width and height in pixels
949
+ * @public
950
+ *
951
+ * @example
952
+ * ```ts
953
+ * const node = { type: 'coupler', data: { couplerFiberCount: 2 } };
954
+ * const dims = getCouplerDimensions(node);
955
+ * // Returns: { width: 80, height: 30 }
956
+ * ```
618
957
  */
619
958
  declare function getCouplerDimensions(node: NetworkNode): {
620
959
  width: number;
@@ -622,6 +961,17 @@ declare function getCouplerDimensions(node: NetworkNode): {
622
961
  };
623
962
  /**
624
963
  * Calculate tube dimensions based on node data
964
+ *
965
+ * @param node - The tube node with optional fibersPerTube in data (default: 12)
966
+ * @returns Object with width and height in pixels
967
+ * @public
968
+ *
969
+ * @example
970
+ * ```ts
971
+ * const node = { type: 'tube', data: { fibersPerTube: 12 } };
972
+ * const dims = getTubeDimensions(node);
973
+ * // Returns: { width: calculated, height: 20 }
974
+ * ```
625
975
  */
626
976
  declare function getTubeDimensions(node: NetworkNode): {
627
977
  width: number;
@@ -629,6 +979,12 @@ declare function getTubeDimensions(node: NetworkNode): {
629
979
  };
630
980
  /**
631
981
  * Get tray dimensions
982
+ *
983
+ * Tray dimensions are fixed and do not depend on node data.
984
+ *
985
+ * @param _node - The tray node (unused, dimensions are fixed)
986
+ * @returns Object with fixed width (TRAY_WIDTH_PX) and height (0)
987
+ * @public
632
988
  */
633
989
  declare function getTrayDimensions(_node: NetworkNode): {
634
990
  width: number;
@@ -636,30 +992,73 @@ declare function getTrayDimensions(_node: NetworkNode): {
636
992
  };
637
993
  /**
638
994
  * Calculate panel width based on content
995
+ *
996
+ * @param panelNode - The panel node with optional panelWidth in data
997
+ * @returns Panel width in pixels, or default PANEL_WIDTH_PX if not specified
998
+ * @public
639
999
  */
640
1000
  declare function getPanelWidth(panelNode: NetworkNode): number;
641
1001
  /**
642
1002
  * Calculate panel height based on content
1003
+ *
1004
+ * @param panelNode - The panel node with optional panelHeight in data
1005
+ * @returns Panel height in pixels, or default PANEL_HEIGHT_PX if not specified
1006
+ * @public
643
1007
  */
644
1008
  declare function getPanelHeight(panelNode: NetworkNode): number;
645
1009
  /**
646
1010
  * Get inner content width (panel width minus borders/padding)
1011
+ *
1012
+ * Calculates the usable width inside a panel after accounting for borders and padding.
1013
+ *
1014
+ * @param panelNode - The panel node
1015
+ * @returns Inner content width in pixels
1016
+ * @public
647
1017
  */
648
1018
  declare function getInnerContentWidth(panelNode: NetworkNode): number;
649
1019
  /**
650
1020
  * Calculate coupler right X position
1021
+ *
1022
+ * Calculates the X position for the right edge of a coupler within a panel.
1023
+ *
1024
+ * @param panelNode - The panel node containing the coupler
1025
+ * @param couplerWidth - Width of the coupler in pixels
1026
+ * @returns X position for the right edge of the coupler
1027
+ * @public
651
1028
  */
652
1029
  declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
653
1030
  /**
654
1031
  * Calculate slot position from Y coordinate
1032
+ *
1033
+ * Converts a Y pixel coordinate to a slot number (1-indexed).
1034
+ *
1035
+ * @param y - Y coordinate in pixels
1036
+ * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)
1037
+ * @returns Slot position (1-indexed)
1038
+ * @public
655
1039
  */
656
1040
  declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
657
1041
  /**
658
1042
  * Calculate Y coordinate from slot position
1043
+ *
1044
+ * Converts a slot number (1-indexed) to a Y pixel coordinate.
1045
+ *
1046
+ * @param slot - Slot position (1-indexed)
1047
+ * @param slotHeight - Height of each slot in pixels (default: COUPLER_SLOT_HEIGHT_PX)
1048
+ * @returns Y coordinate in pixels
1049
+ * @public
659
1050
  */
660
1051
  declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
661
1052
  /**
662
1053
  * Snap coupler to nearest slot position
1054
+ *
1055
+ * Snaps a coupler's position to the nearest valid slot within a panel.
1056
+ *
1057
+ * @param coupler - The coupler node to snap
1058
+ * @param panel - The panel node containing the coupler
1059
+ * @param position - Current position { x, y }
1060
+ * @returns Snapped position with optional slotPosition
1061
+ * @public
663
1062
  */
664
1063
  declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
665
1064
  x: number;
@@ -671,6 +1070,21 @@ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode,
671
1070
  };
672
1071
  /**
673
1072
  * Calculate panel dimensions based on child nodes
1073
+ *
1074
+ * Automatically calculates the width and height of a panel based on its child nodes.
1075
+ * Supports special layouts for patch panels with tubes, trays, and couplers.
1076
+ *
1077
+ * @param panelNode - The panel node
1078
+ * @param childNodes - Array of child nodes within the panel
1079
+ * @returns Object with calculated width and height in pixels
1080
+ * @public
1081
+ *
1082
+ * @example
1083
+ * ```ts
1084
+ * const panel = { id: 'panel-1', type: 'patch-panel', data: {} };
1085
+ * const children = [tubeNode, trayNode, couplerNode];
1086
+ * const dims = calculatePanelDimensions(panel, children);
1087
+ * ```
674
1088
  */
675
1089
  declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
676
1090
  width: number;
@@ -678,10 +1092,27 @@ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: Ne
678
1092
  };
679
1093
  /**
680
1094
  * Calculate spacing between couplers
1095
+ *
1096
+ * Calculates the vertical spacing needed between couplers to fit them evenly
1097
+ * within the available height.
1098
+ *
1099
+ * @param numCouplers - Number of couplers to space
1100
+ * @param couplerHeight - Height of each coupler in pixels
1101
+ * @param availableHeight - Total available height in pixels
1102
+ * @returns Spacing between couplers in pixels (includes coupler height)
1103
+ * @public
681
1104
  */
682
1105
  declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
683
1106
  /**
684
1107
  * Calculate coupler slot spacing
1108
+ *
1109
+ * Alias for calculateCouplerSpacing. Calculates spacing between coupler slots.
1110
+ *
1111
+ * @param numCouplers - Number of couplers to space
1112
+ * @param couplerHeight - Height of each coupler in pixels
1113
+ * @param availableHeight - Total available height in pixels
1114
+ * @returns Spacing between coupler slots in pixels
1115
+ * @public
685
1116
  */
686
1117
  declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
687
1118
 
@@ -727,10 +1158,57 @@ interface DevicePlacementValidation {
727
1158
  }
728
1159
  /**
729
1160
  * Validate device placements within a rack schema
1161
+ *
1162
+ * Checks for out-of-bounds placements and device-to-device conflicts.
1163
+ * Uses the generic validatePlacements utility for consistent validation logic.
1164
+ *
1165
+ * @param rack - The rack configuration to validate
1166
+ * @param _options - Validation options (currently unused)
1167
+ * @returns Validation result with conflicts and out-of-bounds errors
1168
+ * @public
1169
+ *
1170
+ * @example
1171
+ * ```ts
1172
+ * const rack: RackConfig = {
1173
+ * id: 'rack-1',
1174
+ * units: 42,
1175
+ * devices: [
1176
+ * { id: 'dev-1', unit: 1, height: 2, ... },
1177
+ * { id: 'dev-2', unit: 2, height: 1, ... } // Conflicts with dev-1
1178
+ * ]
1179
+ * };
1180
+ * const result = validateRackDevicePlacements(rack);
1181
+ * if (!result.isValid) {
1182
+ * console.log('Conflicts:', result.conflicts);
1183
+ * }
1184
+ * ```
730
1185
  */
731
1186
  declare function validateRackDevicePlacements(rack: RackConfig, _options?: RackSchemaOptions): DevicePlacementValidation;
732
1187
  /**
733
1188
  * Build NetworkNode array from RackConfig array with comprehensive validation
1189
+ *
1190
+ * Converts rack configurations to React Flow nodes with automatic validation
1191
+ * and conflict resolution. Supports strict and nearest conflict policies.
1192
+ *
1193
+ * @param racks - Array of rack configurations
1194
+ * @param options - Build options including conflict policy and validation settings
1195
+ * @returns Array of NetworkNode objects ready for React Flow
1196
+ * @throws {DevicePlacementError} If validation fails in strict mode
1197
+ * @public
1198
+ *
1199
+ * @example
1200
+ * ```ts
1201
+ * const racks: RackConfig[] = [{
1202
+ * id: 'rack-1',
1203
+ * name: 'Main Rack',
1204
+ * units: 42,
1205
+ * devices: [...]
1206
+ * }];
1207
+ * const nodes = buildNodesFromRackConfig(racks, {
1208
+ * conflictPolicy: 'strict',
1209
+ * validatePlacements: true
1210
+ * });
1211
+ * ```
734
1212
  */
735
1213
  declare function buildNodesFromRackConfig(racks: RackConfig[], options?: RackSchemaOptions): NetworkNode[];
736
1214
  /**
@@ -787,10 +1265,55 @@ interface SplicePlacementValidation {
787
1265
  }
788
1266
  /**
789
1267
  * Validate splice placements within a tray schema
1268
+ *
1269
+ * Checks for out-of-bounds placements and splice-to-splice conflicts.
1270
+ * Uses the generic validatePlacements utility for consistent validation logic.
1271
+ *
1272
+ * @param tray - The splice tray configuration to validate
1273
+ * @param _options - Validation options (currently unused)
1274
+ * @returns Validation result with conflicts and out-of-bounds errors
1275
+ * @public
1276
+ *
1277
+ * @example
1278
+ * ```ts
1279
+ * const tray: SpliceTrayConfig = {
1280
+ * id: 'tray-1',
1281
+ * splices: [
1282
+ * { id: 'splice-1', holder: 1, ... },
1283
+ * { id: 'splice-2', holder: 1, ... } // Conflicts with splice-1
1284
+ * ]
1285
+ * };
1286
+ * const result = validateSplicePlacements(tray);
1287
+ * if (!result.isValid) {
1288
+ * console.log('Conflicts:', result.conflicts);
1289
+ * }
1290
+ * ```
790
1291
  */
791
1292
  declare function validateSplicePlacements(tray: SpliceTrayConfig, _options?: SpliceSchemaOptions): SplicePlacementValidation;
792
1293
  /**
793
1294
  * Build NetworkNode array from SpliceTrayConfig array with comprehensive validation
1295
+ *
1296
+ * Converts splice tray configurations to React Flow nodes with automatic validation
1297
+ * and conflict resolution. Supports strict and nearest conflict policies.
1298
+ *
1299
+ * @param trays - Array of splice tray configurations
1300
+ * @param options - Build options including conflict policy and validation settings
1301
+ * @returns Array of NetworkNode objects ready for React Flow
1302
+ * @throws {SplicePlacementError} If validation fails in strict mode
1303
+ * @public
1304
+ *
1305
+ * @example
1306
+ * ```ts
1307
+ * const trays: SpliceTrayConfig[] = [{
1308
+ * id: 'tray-1',
1309
+ * name: 'Tray 1',
1310
+ * splices: [...]
1311
+ * }];
1312
+ * const nodes = buildNodesFromSpliceConfig(trays, {
1313
+ * conflictPolicy: 'strict',
1314
+ * validatePlacements: true
1315
+ * });
1316
+ * ```
794
1317
  */
795
1318
  declare function buildNodesFromSpliceConfig(trays: SpliceTrayConfig[], options?: SpliceSchemaOptions): NetworkNode[];
796
1319
  /**
@@ -939,6 +1462,15 @@ declare function findNearestRack(point: {
939
1462
  y: number;
940
1463
  }, racks: NetworkNode[]): NetworkNode | null;
941
1464
 
1465
+ declare const U_HEIGHT_PX = 20;
1466
+ declare const RACK_HEADER_HEIGHT = 60;
1467
+ declare const RACK_WIDTH_PX = 300;
1468
+ /**
1469
+ * Handle extension in pixels - handles extend this many pixels outside nodes
1470
+ * Used in dimension calculations for panels and closures
1471
+ */
1472
+ declare const HANDLE_EXTENSION_PX = 5;
1473
+
942
1474
  /**
943
1475
  * Options for replacing an edge in the edges array
944
1476
  */
@@ -998,4 +1530,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
998
1530
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
999
1531
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
1000
1532
 
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 };
1533
+ export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, DiagramErrorBoundary, type DiagramErrorBoundaryProps, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, FibreCableWithTubesExpanded, type FibreFlowCable, type FibreFlowCableKind, type FibreFlowCircuit, type FibreFlowClosure, type FibreFlowEndpoint, FibreFlowMap, type FibreFlowMapProps, type FibreFlowSplice, FibreSplitNode, HANDLE_EXTENSION_PX, MultiTubeCableNode, 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, type PortType, PowerEdge, RACK_HEADER_HEIGHT, RACK_WIDTH_PX, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, U_HEIGHT_PX, 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 };