@mp70/react-networks 0.3.1-alpha.0 → 0.5.0-rc.1

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
@@ -65,7 +65,7 @@ interface NetBoxDeviceTransformOptions {
65
65
  includeInterfacePorts?: boolean;
66
66
  /** Include per-port position metadata when provided */
67
67
  includePortPositions?: boolean;
68
- /** Optional mapper for full control over interface->port mapping */
68
+ /** Optional mapper for full control over interface-to-port mapping */
69
69
  mapInterfaceToPort?: (args: {
70
70
  device: NetBoxDevice;
71
71
  iface: NetBoxInterface;
@@ -78,6 +78,7 @@ interface NetBoxDevice {
78
78
  device_type: {
79
79
  id: number;
80
80
  model: string;
81
+ u_height?: number;
81
82
  manufacturer: {
82
83
  name: string;
83
84
  };
@@ -253,7 +254,7 @@ type PortCableType = 'smf' | 'cat6' | 'om3' | 'om4' | 'om5' | 'cat5e' | 'cat6a'
253
254
  *
254
255
  * @public
255
256
  */
256
- type DeviceImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
257
+ type DeviceImageFit = 'cover' | 'contain' | 'contain-height' | 'fill' | 'none' | 'scale-down';
257
258
  /**
258
259
  * Device image repeat options.
259
260
  * @public
@@ -296,10 +297,15 @@ interface PortPosition {
296
297
  xPercent?: number;
297
298
  /** Absolute Y position as percentage (0-100) */
298
299
  yPercent?: number;
300
+ /** Authored port width as a percentage of the rendered image frame */
301
+ widthPercent?: number;
302
+ /** Authored port height as a percentage of the rendered image frame */
303
+ heightPercent?: number;
299
304
  }
300
305
  /**
301
- * Simplified flat port input for device and PDU rendering.
302
- * `react-networks` groups these into front/rear `PortBlock[]` internally.
306
+ * Recommended simple port input for device and PDU rendering.
307
+ * Pass a flat array in `ports`; `react-networks` groups entries into front/rear
308
+ * `PortBlock[]` internally using each port's `face` and `group`.
303
309
  * @public
304
310
  */
305
311
  interface DevicePort {
@@ -308,9 +314,11 @@ interface DevicePort {
308
314
  /** Display label for the port */
309
315
  label: string;
310
316
  /** Front/rear device face. `back` is accepted as an alias for `rear`. */
311
- face?: DeviceView | 'back';
317
+ face?: DeviceFace | 'back';
312
318
  /** Optional block/group name (for example `Network Ports`, `QSFP28`, `Power Ports`) */
313
319
  group?: string;
320
+ /** Optional source/detected family label used for visual kind inference */
321
+ sourceTypeLabel?: string;
314
322
  /** Whether the port is currently connected */
315
323
  connected?: boolean;
316
324
  /** Type of port for styling and validation */
@@ -319,6 +327,8 @@ interface DevicePort {
319
327
  cableType?: PortCableType;
320
328
  /** Optional power connector type for rendering (mainly for PDU ports) */
321
329
  connectorType?: 'C13' | 'C14' | 'C19' | 'C20';
330
+ /** Optional compatibility keys. When omitted, defaults are derived from type/cable/connector data. */
331
+ compatibility?: string[];
322
332
  /** Optional sort order within a face/group bucket */
323
333
  order?: number;
324
334
  /**
@@ -333,6 +343,8 @@ interface Port {
333
343
  id?: string;
334
344
  /** Display label for the port */
335
345
  label: string;
346
+ /** Optional source/detected family label used for visual kind inference */
347
+ sourceTypeLabel?: string;
336
348
  /** Whether the port is currently connected */
337
349
  connected: boolean;
338
350
  /** Type of port for styling and validation */
@@ -341,6 +353,8 @@ interface Port {
341
353
  cableType?: PortCableType;
342
354
  /** Optional power connector type for rendering (mainly for PDU ports) */
343
355
  connectorType?: 'C13' | 'C14' | 'C19' | 'C20';
356
+ /** Optional compatibility keys. When omitted, defaults are derived from type/cable/connector data. */
357
+ compatibility?: string[];
344
358
  /** Optional explicit handle placement */
345
359
  position?: PortPosition;
346
360
  }
@@ -365,10 +379,10 @@ type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patc
365
379
  */
366
380
  type DeviceStatus = 'active' | 'inactive' | 'maintenance';
367
381
  /**
368
- * Device view orientations
382
+ * Device face orientations
369
383
  * @public
370
384
  */
371
- type DeviceView = 'front' | 'rear';
385
+ type DeviceFace = 'front' | 'rear';
372
386
  /**
373
387
  * Rack rendering layout modes.
374
388
  * @public
@@ -399,11 +413,11 @@ interface NetworkNodeDataBase extends DeviceImageOptions {
399
413
  label: string;
400
414
  /** Current status of the node/device */
401
415
  status?: DeviceStatus | string;
402
- /** Flat port input that is normalized into grouped front/rear blocks internally */
416
+ /** Simple flat port input. Use `portGroups` / `rearPortGroups` for explicit grouped control. */
403
417
  ports?: DevicePort[] | number;
404
- /** Lower-level grouped front port input */
418
+ /** Advanced grouped front port input */
405
419
  portGroups?: PortBlock[];
406
- /** Lower-level grouped rear port input */
420
+ /** Advanced grouped rear port input */
407
421
  rearPortGroups?: PortBlock[];
408
422
  /** List of connected node IDs */
409
423
  connections?: string[];
@@ -419,10 +433,10 @@ interface NetworkNodeDataBase extends DeviceImageOptions {
419
433
  uHeight?: number;
420
434
  /** Device position within rack in U units */
421
435
  uPosition?: number;
422
- /** Current front/rear view orientation */
423
- view?: DeviceView;
424
- /** Rack face orientation */
425
- face?: DeviceView;
436
+ /** Whether this node is currently mounted inside a rack container */
437
+ isRackMounted?: boolean;
438
+ /** Front/rear orientation for devices and rack faces */
439
+ face?: DeviceFace;
426
440
  /** Rack rendering layout mode */
427
441
  rackLayout?: RackLayoutMode;
428
442
  /** Gap in pixels between front and rear faces in split-face mode */
@@ -437,7 +451,7 @@ interface NetworkNodeDataBase extends DeviceImageOptions {
437
451
  role?: string;
438
452
  /** Device width configuration */
439
453
  width?: Width | number;
440
- /** Power port side for rear view */
454
+ /** Power port side for rear face */
441
455
  powerSide?: PowerSide;
442
456
  /** Vertical PDU height in centimeters */
443
457
  heightCm?: number;
@@ -545,7 +559,7 @@ interface NetworkNodeDataBase extends DeviceImageOptions {
545
559
  height?: number;
546
560
  headerHeight?: number;
547
561
  /** Optional precomputed map for handle-to-face resolution */
548
- handleSideMap?: Record<string, DeviceView>;
562
+ handleSideMap?: Record<string, DeviceFace>;
549
563
  /** Additional extension metadata */
550
564
  metadata?: Record<string, unknown>;
551
565
  }
@@ -701,9 +715,148 @@ type NetworkEdge<TData extends NetworkEdgeData = NetworkEdgeData> = {
701
715
  targetHandle?: string;
702
716
  /** Type of network connection */
703
717
  type?: NetworkEdgeType;
718
+ /** Whether the edge should be hidden from rendering */
719
+ hidden?: boolean;
704
720
  /** Edge data and configuration */
705
721
  data?: TData;
706
722
  };
723
+ /**
724
+ * Canonical persisted/editor document schema independent from React Flow handle ids.
725
+ * Prefer this model for saving diagrams, syncing external systems, and controlled
726
+ * document-mode usage via `document` / `onDocumentChange`.
727
+ * @public
728
+ */
729
+ interface DiagramDocument {
730
+ nodes: DiagramNode[];
731
+ edges: DiagramEdge[];
732
+ ui?: DiagramUiState;
733
+ metadata?: Record<string, unknown>;
734
+ }
735
+ /**
736
+ * Node kinds used by the document model.
737
+ * @public
738
+ */
739
+ type DiagramNodeKind = 'rack' | 'equipment' | 'pdu' | 'fiber' | 'tube' | 'cable' | 'multi-tube-cable' | 'splice' | 'coupler' | 'splitter' | 'container' | 'fibre-flow-cable' | 'fibre-flow-closure';
740
+ /**
741
+ * Placement data for document nodes.
742
+ * @public
743
+ */
744
+ interface DiagramNodePlacement {
745
+ position: {
746
+ x: number;
747
+ y: number;
748
+ };
749
+ parentId?: string;
750
+ extent?: 'parent';
751
+ rack?: {
752
+ uPosition?: number;
753
+ mountMode?: RackMountMode;
754
+ rackLayout?: RackLayoutMode;
755
+ rackWidthPx?: number;
756
+ rackFaceGapPx?: number;
757
+ };
758
+ container?: {
759
+ slotPosition?: number;
760
+ holderPosition?: number;
761
+ };
762
+ }
763
+ /**
764
+ * Endpoint definition for document nodes.
765
+ * @public
766
+ */
767
+ interface DiagramEndpoint {
768
+ id: string;
769
+ label: string;
770
+ face?: DeviceFace | 'internal';
771
+ group?: string;
772
+ role?: 'network' | 'power' | 'fiber' | 'tube' | 'splice' | 'coupler' | 'splitter' | 'cable' | 'generic';
773
+ medium?: 'ethernet' | 'fiber' | 'power' | 'tube' | 'generic';
774
+ type?: PortType;
775
+ cableType?: PortCableType;
776
+ connector?: string;
777
+ compatibility?: string[];
778
+ layout?: PortPosition;
779
+ }
780
+ /**
781
+ * Render-focused node data for the document model.
782
+ * @public
783
+ */
784
+ interface DiagramNodeRender {
785
+ status?: DeviceStatus | string;
786
+ face?: DeviceFace;
787
+ width?: Width | number;
788
+ widthPx?: number;
789
+ height?: number;
790
+ header?: string;
791
+ color?: string;
792
+ colorMode?: 'light' | 'dark' | 'system';
793
+ rackWidthPx?: number;
794
+ rackFaceGapPx?: number;
795
+ images?: DeviceImageOptions;
796
+ dimensions?: Record<string, number | undefined>;
797
+ showUMarkers?: boolean;
798
+ customHeaderText?: string;
799
+ powerSide?: PowerSide;
800
+ rotation?: number;
801
+ }
802
+ /**
803
+ * External reference attached to a document node.
804
+ * @public
805
+ */
806
+ interface DiagramExternalRef {
807
+ source: 'netbox' | 'inventory' | string;
808
+ id: string | number;
809
+ type?: string;
810
+ metadata?: Record<string, unknown>;
811
+ }
812
+ /**
813
+ * Document node.
814
+ * @public
815
+ */
816
+ interface DiagramNode {
817
+ id: string;
818
+ kind: DiagramNodeKind;
819
+ subtype?: string;
820
+ label: string;
821
+ placement: DiagramNodePlacement;
822
+ endpoints?: DiagramEndpoint[];
823
+ render?: DiagramNodeRender;
824
+ config?: Record<string, unknown>;
825
+ externalRefs?: DiagramExternalRef[];
826
+ metadata?: Record<string, unknown>;
827
+ }
828
+ /**
829
+ * Endpoint reference used by document edges.
830
+ * @public
831
+ */
832
+ interface DiagramEdgeEndpoint {
833
+ nodeId: string;
834
+ endpointId?: string | null;
835
+ }
836
+ /**
837
+ * Document edge.
838
+ * @public
839
+ */
840
+ interface DiagramEdge {
841
+ id: string;
842
+ source: DiagramEdgeEndpoint;
843
+ target: DiagramEdgeEndpoint;
844
+ type?: NetworkEdgeType;
845
+ hidden?: boolean;
846
+ data?: NetworkEdgeData;
847
+ metadata?: Record<string, unknown>;
848
+ }
849
+ /**
850
+ * Non-topology UI state stored alongside a document.
851
+ * @public
852
+ */
853
+ interface DiagramUiState {
854
+ nodeState?: Record<string, {
855
+ face?: DeviceFace;
856
+ handleSideMap?: Record<string, DeviceFace>;
857
+ }>;
858
+ metadata?: Record<string, unknown>;
859
+ }
707
860
  /**
708
861
  * Rack device types
709
862
  * @public
@@ -759,15 +912,15 @@ interface RackDevice extends DeviceImageOptions {
759
912
  mountMode?: RackMountMode;
760
913
  /** Device role in network */
761
914
  role?: string;
762
- /** Flat port input normalized by the renderer */
915
+ /** Recommended simple port input. Use `portGroups` / `rearPortGroups` for explicit grouped control. */
763
916
  ports?: DevicePort[];
764
917
  /** Current status of the device */
765
918
  status?: DeviceStatus | string;
766
- /** Lower-level grouped front port input */
919
+ /** Advanced grouped front port input */
767
920
  portGroups?: PortBlock[];
768
- /** Lower-level grouped rear port input */
921
+ /** Advanced grouped rear port input */
769
922
  rearPortGroups?: PortBlock[];
770
- /** Power port side for rear view */
923
+ /** Power port side for rear face */
771
924
  powerSide?: PowerSide;
772
925
  /** Connected device IDs */
773
926
  connections?: string[];
@@ -935,36 +1088,43 @@ interface NetworkDiagramFlowMethods {
935
1088
  getEdges: () => NetworkEdge[];
936
1089
  fitView: (options?: NetworkDiagramFitViewOptions) => void;
937
1090
  }
1091
+ /**
1092
+ * Store state shape used by `NetworkDiagramStoreApi`.
1093
+ * @public
1094
+ */
1095
+ interface NetworkDiagramStoreState {
1096
+ nodes: NetworkNode[];
1097
+ edges: NetworkEdge[];
1098
+ debug?: boolean;
1099
+ }
1100
+ /**
1101
+ * Store connection validation parameters.
1102
+ * @public
1103
+ */
1104
+ interface NetworkDiagramValidateConnectionParams {
1105
+ source: string | null;
1106
+ target: string | null;
1107
+ sourceHandle?: string | null;
1108
+ targetHandle?: string | null;
1109
+ }
1110
+ /**
1111
+ * Store connection validation result.
1112
+ * @public
1113
+ */
1114
+ interface NetworkDiagramValidationResult {
1115
+ valid: boolean;
1116
+ reason?: string;
1117
+ }
938
1118
  /**
939
1119
  * Store contract accepted by `NetworkDiagram`.
940
1120
  * @public
941
1121
  */
942
1122
  interface NetworkDiagramStoreApi {
943
- getState: () => {
944
- nodes: NetworkNode[];
945
- edges: NetworkEdge[];
946
- debug?: boolean;
947
- };
948
- setState: (partial: Partial<{
949
- nodes: NetworkNode[];
950
- edges: NetworkEdge[];
951
- debug?: boolean;
952
- }>) => void;
953
- subscribe: (listener: (state: {
954
- nodes: NetworkNode[];
955
- edges: NetworkEdge[];
956
- debug?: boolean;
957
- }) => void) => () => void;
1123
+ getState: () => NetworkDiagramStoreState;
1124
+ setState: (partial: Partial<NetworkDiagramStoreState>) => void;
1125
+ subscribe: (listener: (state: NetworkDiagramStoreState) => void) => () => void;
958
1126
  selectEdgeZIndex: (edge: NetworkEdge) => number;
959
- validateConnection: (params: {
960
- source: string | null;
961
- target: string | null;
962
- sourceHandle?: string | null;
963
- targetHandle?: string | null;
964
- }) => {
965
- valid: boolean;
966
- reason?: string;
967
- };
1127
+ validateConnection: (params: NetworkDiagramValidateConnectionParams) => NetworkDiagramValidationResult;
968
1128
  selectNodeById: (id: string) => NetworkNode | undefined;
969
1129
  selectConnectedEdges: (nodeId: string) => NetworkEdge[];
970
1130
  }
@@ -973,6 +1133,12 @@ interface NetworkDiagramStoreApi {
973
1133
  * @public
974
1134
  */
975
1135
  interface NetworkDiagramProps {
1136
+ /** Controlled document model. When provided, it takes precedence over nodes/edges props. */
1137
+ document?: DiagramDocument;
1138
+ /** Initial document for uncontrolled document mode. */
1139
+ initialDocument?: DiagramDocument;
1140
+ /** Callback when the document changes in document mode. */
1141
+ onDocumentChange?: (document: DiagramDocument) => void;
976
1142
  /** Controlled nodes array */
977
1143
  nodes?: NetworkNode[];
978
1144
  /** Controlled edges array */
@@ -1005,10 +1171,10 @@ interface NetworkDiagramProps {
1005
1171
  isValidConnection?: (connection: Connection) => boolean;
1006
1172
  /** Optional connection mode override */
1007
1173
  connectionMode?: ConnectionMode;
1008
- /** Callback when device view changes */
1009
- onViewChange?: (nodeId: string, view: DeviceView) => void;
1174
+ /** Callback when a device face changes */
1175
+ onFaceChange?: (nodeId: string, face: DeviceFace) => void;
1010
1176
  /** Callback when rack face changes */
1011
- onRackFaceChange?: (rackId: string, face: DeviceView) => void;
1177
+ onRackFaceChange?: (rackId: string, face: DeviceFace) => void;
1012
1178
  /** CSS class name */
1013
1179
  className?: string;
1014
1180
  /** Inline styles */
@@ -1039,42 +1205,15 @@ interface NetworkDiagramProps {
1039
1205
  interaction?: NetworkDiagramInteractionOptions;
1040
1206
  /** Configuration for the floating action panel shown on selected rack/device nodes. */
1041
1207
  actionPanel?: NetworkDiagramActionPanelOptions;
1042
- /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */
1043
- connectOnClick?: boolean;
1044
- /** Disable panning on drag. Default is false. */
1045
- panOnDrag?: boolean;
1046
- /** Disable panning on scroll. Default is true. */
1047
- panOnScroll?: boolean;
1048
- /** Disable zooming on scroll. Default is true. */
1049
- zoomOnScroll?: boolean;
1050
1208
  /** Optional fitView options passed to React Flow */
1051
1209
  fitViewOptions?: FitViewOptions;
1210
+ /**
1211
+ * Let React Flow render only viewport-visible nodes and edges.
1212
+ * Defaults to true, matching the library's existing large-diagram behavior.
1213
+ */
1214
+ onlyRenderVisibleElements?: boolean;
1052
1215
  }
1053
1216
 
1054
- /**
1055
- * Main component for rendering interactive network diagrams.
1056
- *
1057
- * The NetworkDiagram component provides a complete solution for visualizing
1058
- * network infrastructure including racks, devices, fiber connections, and power distribution.
1059
- *
1060
- * @example
1061
- * ```tsx
1062
- * import { NetworkDiagram, NetworkNode, NetworkEdge } from '@mp70/react-networks';
1063
- *
1064
- * const nodes: NetworkNode[] = [
1065
- * {
1066
- * id: 'rack-1',
1067
- * type: 'rack',
1068
- * position: { x: 100, y: 100 },
1069
- * data: { label: 'Main Rack', uHeight: 42 }
1070
- * }
1071
- * ];
1072
- *
1073
- * <NetworkDiagram nodes={nodes} edges={[]} />
1074
- * ```
1075
- *
1076
- * @public
1077
- */
1078
1217
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
1079
1218
 
1080
1219
  interface DiagramErrorBoundaryProps {
@@ -1085,7 +1224,7 @@ interface DiagramErrorBoundaryProps {
1085
1224
  /** Optional callback when an error is caught (e.g. for logging) */
1086
1225
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
1087
1226
  }
1088
- interface State {
1227
+ interface DiagramErrorBoundaryState {
1089
1228
  error: Error | null;
1090
1229
  }
1091
1230
  /**
@@ -1108,23 +1247,23 @@ interface State {
1108
1247
  * </DiagramErrorBoundary>
1109
1248
  * ```
1110
1249
  */
1111
- declare class DiagramErrorBoundary extends Component<DiagramErrorBoundaryProps, State> {
1112
- state: State;
1113
- static getDerivedStateFromError(error: Error): State;
1250
+ declare class DiagramErrorBoundary extends Component<DiagramErrorBoundaryProps, DiagramErrorBoundaryState> {
1251
+ state: DiagramErrorBoundaryState;
1252
+ static getDerivedStateFromError(error: Error): DiagramErrorBoundaryState;
1114
1253
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
1115
1254
  reset: () => void;
1116
1255
  render(): ReactNode;
1117
1256
  }
1118
1257
 
1119
1258
  interface RackNodeProps extends NodeProps<NetworkNode['data']> {
1120
- onViewChange?: (nodeId: string, view: 'front' | 'rear') => void;
1259
+ onFaceChange?: (nodeId: string, face: 'front' | 'rear') => void;
1121
1260
  onRackFaceChange?: (rackId: string, face: 'front' | 'rear') => void;
1122
1261
  isDragOver?: boolean;
1123
1262
  }
1124
1263
  /**
1125
1264
  * Rack visualization component with U positioning support.
1126
1265
  *
1127
- * Displays a 19" rack with configurable height, front/rear view switching,
1266
+ * Displays a 19" rack with configurable height, front/rear face switching,
1128
1267
  * and support for mounting devices at specific U positions.
1129
1268
  *
1130
1269
  * @example
@@ -1194,12 +1333,9 @@ declare const PowerEdge: React$1.FC<EdgeProps>;
1194
1333
  * label: 'Web Server',
1195
1334
  * deviceType: 'server',
1196
1335
  * uPosition: 1,
1197
- * ports: [{
1198
- * name: 'Network Ports',
1199
- * ports: [
1200
- * { label: 'eth0', connected: true, type: 'ethernet' }
1201
- * ]
1202
- * }]
1336
+ * ports: [
1337
+ * { id: 'eth0', label: 'eth0', group: 'Network Ports', connected: true, type: 'ethernet' }
1338
+ * ]
1203
1339
  * }
1204
1340
  * }
1205
1341
  * ```
@@ -1275,9 +1411,7 @@ interface FibreFlowMapProps {
1275
1411
  className?: string;
1276
1412
  style?: React$1.CSSProperties;
1277
1413
  readOnly?: boolean;
1278
- panOnDrag?: boolean;
1279
- panOnScroll?: boolean;
1280
- zoomOnScroll?: boolean;
1414
+ interaction?: NetworkDiagramInteractionOptions;
1281
1415
  }
1282
1416
  declare const FibreFlowMap: React$1.FC<FibreFlowMapProps>;
1283
1417
 
@@ -1418,6 +1552,14 @@ declare const inventoryToNetworkDiagram: (data: {
1418
1552
  nodes: NetworkNode[];
1419
1553
  edges: NetworkEdge[];
1420
1554
  };
1555
+ /**
1556
+ * Convert inventory data directly into the canonical DiagramDocument model.
1557
+ */
1558
+ declare const inventoryToDiagramDocument: (data: {
1559
+ racks: InventoryRackDTO[];
1560
+ devices: InventoryDeviceDTO[];
1561
+ cables: InventoryCableDTO[];
1562
+ }) => DiagramDocument;
1421
1563
  /**
1422
1564
  * Generate simple layout positions for nodes array
1423
1565
  */
@@ -1446,6 +1588,14 @@ declare const netboxToNetworkDiagram: (data: {
1446
1588
  nodes: NetworkNode[];
1447
1589
  edges: NetworkEdge[];
1448
1590
  };
1591
+ /**
1592
+ * Convert NetBox data directly into the canonical DiagramDocument model.
1593
+ */
1594
+ declare const netboxToDiagramDocument: (data: {
1595
+ racks: NetBoxRack[];
1596
+ devices: NetBoxDevice[];
1597
+ cables: NetBoxCable[];
1598
+ }, options?: NetBoxDeviceTransformOptions) => DiagramDocument;
1449
1599
  /**
1450
1600
  * Calculate U position for devices in a rack
1451
1601
  */
@@ -1963,18 +2113,91 @@ declare function addSpliceToTray(trays: SpliceTrayConfig[], trayId: string, spli
1963
2113
  */
1964
2114
  declare function removeSpliceFromTray(trays: SpliceTrayConfig[], trayId: string, spliceId: string): SpliceTrayConfig[];
1965
2115
 
1966
- type PortFaces = {
2116
+ /**
2117
+ * Normalize flat `DevicePort[]` input into explicit front/rear grouped blocks.
2118
+ * This is the bridge between the recommended simple port schema and the
2119
+ * lower-level grouped renderer input.
2120
+ * @public
2121
+ */
2122
+ declare function buildPortBlocksFromPorts(devicePorts: DevicePort[]): {
2123
+ ports: PortBlock[];
2124
+ rearPorts: PortBlock[];
2125
+ };
2126
+ /**
2127
+ * Resolve the grouped front/rear port blocks from either supported input form:
2128
+ * flat `ports: DevicePort[]` or explicit `portGroups` / `rearPortGroups`.
2129
+ * @public
2130
+ */
2131
+ declare function getResolvedPortBlocks(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): {
1967
2132
  ports: PortBlock[];
1968
2133
  rearPorts: PortBlock[];
1969
2134
  };
1970
- type PortFaceData = Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'>;
1971
- declare function buildPortBlocksFromPorts(devicePorts: DevicePort[]): PortFaces;
1972
- declare function getResolvedPortBlocks(data: PortFaceData | undefined): PortFaces;
1973
- declare function getFrontPortBlocks(data: PortFaceData | undefined): PortBlock[];
1974
- declare function getRearPortBlocks(data: PortFaceData | undefined): PortBlock[];
1975
- declare function hasFrontPorts(data: PortFaceData | undefined): boolean;
1976
- declare function hasRearPorts(data: PortFaceData | undefined): boolean;
1977
- declare function getDefaultDeviceView(data: PortFaceData | undefined): DeviceView;
2135
+ /**
2136
+ * Resolve the front-facing grouped port blocks for a node/device data object.
2137
+ * @public
2138
+ */
2139
+ declare function getFrontPortBlocks(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): PortBlock[];
2140
+ /**
2141
+ * Resolve the rear-facing grouped port blocks for a node/device data object.
2142
+ * @public
2143
+ */
2144
+ declare function getRearPortBlocks(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): PortBlock[];
2145
+ /**
2146
+ * Determine whether a node/device data object resolves to any front ports.
2147
+ * @public
2148
+ */
2149
+ declare function hasFrontPorts(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): boolean;
2150
+ /**
2151
+ * Determine whether a node/device data object resolves to any rear ports.
2152
+ * @public
2153
+ */
2154
+ declare function hasRearPorts(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): boolean;
2155
+ /**
2156
+ * Choose the default device face based on the resolved front/rear port data.
2157
+ * @public
2158
+ */
2159
+ declare function getDefaultDeviceFace(data: Pick<NetworkNode['data'], 'ports' | 'portGroups' | 'rearPortGroups'> | undefined): DeviceFace;
2160
+
2161
+ interface NetworkGraphSnapshot {
2162
+ nodes: NetworkNode[];
2163
+ edges: NetworkEdge[];
2164
+ }
2165
+ declare function networkGraphToDiagramDocument(snapshot: NetworkGraphSnapshot, previousDocument?: DiagramDocument): DiagramDocument;
2166
+ declare function diagramDocumentToNetworkGraph(document: DiagramDocument): NetworkGraphSnapshot;
2167
+
2168
+ type EndpointConnectionKind = 'power' | 'network' | 'unknown';
2169
+ interface EndpointMetadata {
2170
+ normalizedHandle: string;
2171
+ face?: DeviceFace;
2172
+ kind: EndpointConnectionKind;
2173
+ compatibility: string[];
2174
+ }
2175
+ declare function resolveEndpointCompatibilityKeys(input: {
2176
+ compatibility?: string[];
2177
+ kind?: EndpointConnectionKind;
2178
+ type?: string;
2179
+ cableType?: string;
2180
+ connectorType?: string;
2181
+ handleId?: string;
2182
+ }): string[];
2183
+ declare function getEndpointMetadata(node?: NetworkNode, handle?: string | null): EndpointMetadata;
2184
+
2185
+ type PortVisualKind = 'generic' | 'rj45' | 'sfp' | 'qsfp' | 'osfp' | 'console' | 'usb' | 'power_c13' | 'power_c19' | 'power_ac';
2186
+ interface PortVisualInput {
2187
+ type?: PortType | string;
2188
+ label?: string;
2189
+ id?: string;
2190
+ group?: string;
2191
+ sourceTypeLabel?: string;
2192
+ connectorType?: string;
2193
+ }
2194
+ interface PortVisualDimensions {
2195
+ width: number;
2196
+ height: number;
2197
+ borderRadius: string;
2198
+ }
2199
+ declare function resolvePortVisualKind(input: PortVisualInput): PortVisualKind;
2200
+ declare function getStandardPortVisualDimensions(inputOrKind: PortVisualInput | PortVisualKind): PortVisualDimensions | undefined;
1978
2201
 
1979
2202
  /**
1980
2203
  * Power connector utilities for consistent styling across devices and PDUs
@@ -2307,6 +2530,10 @@ interface TemplateParseResult {
2307
2530
  *
2308
2531
  * **Port position semantics**: Positions use `xPercent` / `yPercent` (0-100)
2309
2532
  * to express where the port CENTER should be relative to the device face.
2533
+ * Raw imports may also use semantic edge strings like `top-left` or
2534
+ * `right-middle`; those are normalized into side/offset placements during
2535
+ * import. `xPercent` / `yPercent` remain the manual override path for
2536
+ * detailed templates.
2310
2537
  * The renderer (`DeviceNode`) converts these to pixel coordinates and clamps
2311
2538
  * them so the port stays fully inside the device bounds. Clamp bounds are
2312
2539
  * computed from the **actual** rendered port dimensions (which vary by port
@@ -2328,7 +2555,7 @@ interface RawTemplatePort {
2328
2555
  type?: string;
2329
2556
  connectorType?: string;
2330
2557
  connector_type?: string;
2331
- position?: {
2558
+ position?: string | {
2332
2559
  side?: string;
2333
2560
  offsetPercent?: number;
2334
2561
  offset_percent?: number;
@@ -2447,4 +2674,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
2447
2674
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
2448
2675
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
2449
2676
 
2450
- export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, type DeviceImageFit, type DeviceImageOptions, type DeviceImageRepeat, DeviceNode, DevicePlacementError, type DevicePlacementValidation, type DevicePort, type DeviceTemplateV2, DiagramErrorBoundary, type DiagramErrorBoundaryProps, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, FibreCableWithTubesExpanded, type FibreFlowCable, type FibreFlowCableKind, type FibreFlowCableNodeData, type FibreFlowCircuit, type FibreFlowClosure, type FibreFlowClosureNodeData, type FibreFlowEndpoint, FibreFlowMap, type FibreFlowMapProps, type FibreFlowSplice, FibreSplitNode, HANDLE_EXTENSION_PX, type MountClass, MultiTubeCableNode, NetworkDiagram, type NetworkDiagramFitViewOptions, type NetworkDiagramFlowMethods, type NetworkDiagramFlowObject, type NetworkDiagramOptions, type NetworkDiagramProps, type NetworkDiagramStoreApi, type NetworkDiagramToImageOptions, type NetworkEdge, type NetworkEdgeData, type NetworkNode, type NetworkNodeData, type NetworkNodeDataBase, type NetworkNodeDataByType, 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 PortCableType, type PortType, PowerEdge, RACK_HEADER_HEIGHT, RACK_WIDTH_PX, type RackConfig, type RackDevice, type RackLayoutMode, type RackMountMode, RackNode, type RackSchemaOptions, type RawNetboxTemplate, type RawTemplatePort, type RawTemplatePortBlock, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TEMPLATE_SCHEMA_VERSION, type TemplateFaceData, type TemplateFrontRearPortLink, type TemplateParseResult, type TemplatePort, type TemplatePortBlock, type TemplateSource, type TemplateValidationIssue, type TemplateValidationReport, type TemplateWidth, TubeNode, U_HEIGHT_PX, type ValidateConnectionParams, type ValidationResult, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, buildPortBlocksFromPorts, calculateClosureDimensions, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateUPositions, calculateYFromSlotPosition, countTemplateFacePorts, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDefaultDeviceView, getDeviceConnectorType, getFiberColor, getFrontPortBlocks, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getRearPortBlocks, getResolvedPortBlocks, getStatusColor, getTrayDimensions, getTubeDimensions, hasFrontPorts, hasRearPorts, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, netboxCableToNetworkEdge, netboxDeviceToNetworkNode, netboxRackToNetworkNode, netboxToNetworkDiagram, parseNetboxTemplate, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateRenderFidelity, validateSplicePlacements };
2677
+ export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, type DeviceFace, type DeviceImageFit, type DeviceImageOptions, type DeviceImageRepeat, DeviceNode, type DeviceNodeData, DevicePlacementError, type DevicePlacementValidation, type DevicePort, type DeviceStatus, type DeviceTemplateV2, type DiagramDocument, type DiagramEdge, type DiagramEdgeEndpoint, type DiagramEndpoint, DiagramErrorBoundary, type DiagramErrorBoundaryProps, type DiagramErrorBoundaryState, type DiagramExternalRef, type DiagramNode, type DiagramNodeKind, type DiagramNodePlacement, type DiagramNodeRender, type DiagramUiState, type EndpointConnectionKind, type EndpointMetadata, FIBER_COLORS_12, type FiberCable, type FiberCableType, type FiberColorId, FiberEdge, FiberNode, FibreCableWithTubesExpanded, type FibreCableWithTubesExpandedProps, type FibreFlowCable, type FibreFlowCableKind, type FibreFlowCableLayout, type FibreFlowCableNodeData, type FibreFlowCircuit, type FibreFlowClosure, type FibreFlowClosureNodeData, type FibreFlowColorMode, type FibreFlowEndpoint, type FibreFlowLayoutDirection, FibreFlowMap, type FibreFlowMapProps, type FibreFlowRow, type FibreFlowSplice, type FibreFlowTubeLabel, FibreSplitNode, HANDLE_EXTENSION_PX, type InventoryCableDTO, type InventoryDeviceDTO, type InventoryRackDTO, type MountClass, MultiTubeCableNode, type NetBoxCable, type NetBoxDevice, type NetBoxDeviceTransformOptions, type NetBoxInterface, type NetBoxMappedPort, type NetBoxPortPosition, type NetBoxRack, NetworkDiagram, type NetworkDiagramActionPanelOptions, type NetworkDiagramFitViewOptions, type NetworkDiagramFlowMethods, type NetworkDiagramFlowObject, type NetworkDiagramInteractionOptions, type NetworkDiagramOptions, type NetworkDiagramProps, type NetworkDiagramState, type NetworkDiagramStore, type NetworkDiagramStoreApi, type NetworkDiagramStoreState, type NetworkDiagramToImageOptions, type NetworkDiagramValidateConnectionParams, type NetworkDiagramValidationResult, type NetworkEdge, type NetworkEdgeData, type NetworkEdgeType, type NetworkGraphSnapshot, type NetworkNode, type NetworkNodeData, type NetworkNodeDataBase, type NetworkNodeDataByType, type NetworkNodeType, 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 PortCableType, type PortPosition, type PortType, type PortVisualDimensions, type PortVisualInput, type PortVisualKind, type PowerConnectorConfig, PowerEdge, type PowerPortStyle, type PowerSide, RACK_HEADER_HEIGHT, RACK_WIDTH_PX, type RackConfig, type RackDevice, type RackDeviceType, type RackLayoutMode, type RackMountMode, type RackMountedNodeType, RackNode, type RackNodeData, type RackNodeProps, type RackSchemaOptions, type RawNetboxTemplate, type RawTemplatePort, type RawTemplatePortBlock, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TEMPLATE_SCHEMA_VERSION, type TemplateFaceData, type TemplateFrontRearPortLink, type TemplateParseResult, type TemplatePort, type TemplatePortBlock, type TemplateSource, type TemplateValidationIssue, type TemplateValidationReport, type TemplateWidth, TubeNode, type UNumberingDirection, U_HEIGHT_PX, type ValidateConnectionParams, type ValidationResult, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, buildPortBlocksFromPorts, calculateClosureDimensions, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateUPositions, calculateYFromSlotPosition, countTemplateFacePorts, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, diagramDocumentToNetworkGraph, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDefaultDeviceFace, getDeviceConnectorType, getEndpointMetadata, getFiberColor, getFrontPortBlocks, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getRearPortBlocks, getResolvedPortBlocks, getStandardPortVisualDimensions, getStatusColor, getTrayDimensions, getTubeDimensions, hasFrontPorts, hasRearPorts, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToDiagramDocument, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, netboxCableToNetworkEdge, netboxDeviceToNetworkNode, netboxRackToNetworkNode, netboxToDiagramDocument, netboxToNetworkDiagram, networkGraphToDiagramDocument, parseNetboxTemplate, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, resolveEndpointCompatibilityKeys, resolvePortVisualKind, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateRenderFidelity, validateSplicePlacements };