@mp70/react-networks 0.1.8-beta → 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.ts 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",
@@ -44,7 +45,7 @@ interface PortBlock {
44
45
  * Network node types supported by the diagram
45
46
  * @public
46
47
  */
47
- type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'multi-tube-cable' | 'coupler' | 'closure' | 'fibre-split';
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';
48
49
  /**
49
50
  * Device status states
50
51
  * @public
@@ -115,6 +116,16 @@ interface NetworkNode {
115
116
  rearPorts?: PortBlock[];
116
117
  /** Power port side for rear view */
117
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';
118
129
  /** Vertical PDU height in centimeters */
119
130
  heightCm?: number;
120
131
  /** Number of AC power ports */
@@ -163,7 +174,7 @@ interface NetworkNode {
163
174
  * Network edge types
164
175
  * @public
165
176
  */
166
- type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable';
177
+ type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable' | 'fibre-flow' | 'fibre-flow-link';
167
178
  /**
168
179
  * Network edge data structure
169
180
  * @public
@@ -262,6 +273,16 @@ interface RackDevice {
262
273
  rearPorts?: PortBlock[];
263
274
  /** Power port side for rear view */
264
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';
265
286
  /** Connected device IDs */
266
287
  connections?: string[];
267
288
  }
@@ -353,6 +374,18 @@ interface NetworkDiagramProps {
353
374
  onNodeClick?: (node: NetworkNode | null) => void;
354
375
  /** Callback when an edge is clicked */
355
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;
356
389
  /** Callback when device view changes */
357
390
  onViewChange?: (nodeId: string, view: DeviceView) => void;
358
391
  /** Callback when rack face changes */
@@ -396,25 +429,165 @@ interface NetworkDiagramProps {
396
429
  panOnScroll?: boolean;
397
430
  /** Disable zooming on scroll. Default is true. */
398
431
  zoomOnScroll?: boolean;
432
+ /** Optional fitView options passed to React Flow */
433
+ fitViewOptions?: FitViewOptions;
399
434
  }
400
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
+ */
401
460
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
402
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
+
403
501
  interface RackNodeProps extends NodeProps<NetworkNode['data']> {
404
502
  onViewChange?: (nodeId: string, view: 'front' | 'rear') => void;
405
503
  onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void;
406
504
  isDragOver?: boolean;
407
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
+ */
408
528
  declare const RackNode: React$1.FC<RackNodeProps>;
409
529
 
410
530
  declare const FiberNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
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
+ */
412
556
  declare const FiberEdge: React$1.FC<EdgeProps<NetworkEdge['data']> & {
413
557
  className?: string;
414
558
  }>;
415
559
 
416
560
  declare const PowerEdge: React$1.FC<EdgeProps>;
417
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
+ */
418
591
  declare const DeviceNode: React$1.FC<NodeProps<NetworkNode['data']>>;
419
592
 
420
593
  declare const VerticalPDU: React$1.FC<NodeProps<NetworkNode['data']>>;
@@ -465,6 +638,105 @@ declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
465
638
  */
466
639
  declare const FibreSplitNode: React$1.FC<NodeProps<NetworkNode['data']>>;
467
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
+
468
740
  interface InventoryRackDTO {
469
741
  id: string | number;
470
742
  name: string;
@@ -671,6 +943,17 @@ declare const PANEL_PADDING = 8;
671
943
  declare const PANEL_TUBE_TRAY_SPACING = 120;
672
944
  /**
673
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
+ * ```
674
957
  */
675
958
  declare function getCouplerDimensions(node: NetworkNode): {
676
959
  width: number;
@@ -678,6 +961,17 @@ declare function getCouplerDimensions(node: NetworkNode): {
678
961
  };
679
962
  /**
680
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
+ * ```
681
975
  */
682
976
  declare function getTubeDimensions(node: NetworkNode): {
683
977
  width: number;
@@ -685,6 +979,12 @@ declare function getTubeDimensions(node: NetworkNode): {
685
979
  };
686
980
  /**
687
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
688
988
  */
689
989
  declare function getTrayDimensions(_node: NetworkNode): {
690
990
  width: number;
@@ -692,30 +992,73 @@ declare function getTrayDimensions(_node: NetworkNode): {
692
992
  };
693
993
  /**
694
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
695
999
  */
696
1000
  declare function getPanelWidth(panelNode: NetworkNode): number;
697
1001
  /**
698
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
699
1007
  */
700
1008
  declare function getPanelHeight(panelNode: NetworkNode): number;
701
1009
  /**
702
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
703
1017
  */
704
1018
  declare function getInnerContentWidth(panelNode: NetworkNode): number;
705
1019
  /**
706
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
707
1028
  */
708
1029
  declare function calculateCouplerRightX(panelNode: NetworkNode, couplerWidth: number): number;
709
1030
  /**
710
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
711
1039
  */
712
1040
  declare function calculateSlotPositionFromY(y: number, slotHeight?: number): number;
713
1041
  /**
714
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
715
1050
  */
716
1051
  declare function calculateYFromSlotPosition(slot: number, slotHeight?: number): number;
717
1052
  /**
718
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
719
1062
  */
720
1063
  declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode, position: {
721
1064
  x: number;
@@ -727,6 +1070,21 @@ declare function snapToCouplerPosition(coupler: NetworkNode, panel: NetworkNode,
727
1070
  };
728
1071
  /**
729
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
+ * ```
730
1088
  */
731
1089
  declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: NetworkNode[]): {
732
1090
  width: number;
@@ -734,10 +1092,27 @@ declare function calculatePanelDimensions(panelNode: NetworkNode, childNodes: Ne
734
1092
  };
735
1093
  /**
736
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
737
1104
  */
738
1105
  declare function calculateCouplerSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
739
1106
  /**
740
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
741
1116
  */
742
1117
  declare function calculateCouplerSlotSpacing(numCouplers: number, couplerHeight: number, availableHeight: number): number;
743
1118
 
@@ -783,10 +1158,57 @@ interface DevicePlacementValidation {
783
1158
  }
784
1159
  /**
785
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
+ * ```
786
1185
  */
787
1186
  declare function validateRackDevicePlacements(rack: RackConfig, _options?: RackSchemaOptions): DevicePlacementValidation;
788
1187
  /**
789
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
+ * ```
790
1212
  */
791
1213
  declare function buildNodesFromRackConfig(racks: RackConfig[], options?: RackSchemaOptions): NetworkNode[];
792
1214
  /**
@@ -843,10 +1265,55 @@ interface SplicePlacementValidation {
843
1265
  }
844
1266
  /**
845
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
+ * ```
846
1291
  */
847
1292
  declare function validateSplicePlacements(tray: SpliceTrayConfig, _options?: SpliceSchemaOptions): SplicePlacementValidation;
848
1293
  /**
849
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
+ * ```
850
1317
  */
851
1318
  declare function buildNodesFromSpliceConfig(trays: SpliceTrayConfig[], options?: SpliceSchemaOptions): NetworkNode[];
852
1319
  /**
@@ -995,6 +1462,15 @@ declare function findNearestRack(point: {
995
1462
  y: number;
996
1463
  }, racks: NetworkNode[]): NetworkNode | null;
997
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
+
998
1474
  /**
999
1475
  * Options for replacing an edge in the edges array
1000
1476
  */
@@ -1054,4 +1530,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
1054
1530
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
1055
1531
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
1056
1532
 
1057
- 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, FibreSplitNode, 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, 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 };