import { Node } from '@xyflow/react'; type FibreFlowCableKind = 'simple' | 'tube'; interface FibreFlowCable { id: string; label: string; kind?: FibreFlowCableKind; fiberCount?: number; tubeCount?: number; fibersPerTube?: number; tubeStartIndex?: number; fiberStartIndex?: number; tubeColorMap?: Record; jacketColor?: string; distanceLabel?: string; distanceMeters?: number; } /** * Rack device width configuration * @public */ declare enum Width { /** Full width device (19" rack width) */ FULL = "full", /** Half width device (9.5" rack width) */ HALF = "half" } /** * Port configuration for network devices * @public */ /** * Port type enumeration * @public */ type PortType = "ethernet" | "rj45" | "fiber" | "console" | "mgmt" | "usb" | "vga" | "serial" | "power_ac" | "power_c13" | "power_c19"; /** * Cable types used for connected network ports. * @public */ type PortCableType = "smf" | "cat6" | "om3" | "om4" | "om5" | "cat5e" | "cat6a" | "cat7" | "fiber" | "ethernet"; /** * Device image fit options. * * Values mirror object-fit terms for API ergonomics and are mapped to valid * background-size values by renderers where needed. * * @public */ type DeviceImageFit = "cover" | "contain" | "contain-height" | "fill" | "none" | "scale-down"; /** * Device image repeat options. * @public */ type DeviceImageRepeat = "no-repeat" | "repeat" | "repeat-x" | "repeat-y"; /** * Shared image configuration for rack-mounted devices and device nodes. * @public */ interface DeviceImageOptions { /** Optional front image URL for device background (PNG, SVG, JPEG, etc.) */ frontImageUrl?: string; /** Optional rear image URL for device background (PNG, SVG, JPEG, etc.) */ rearImageUrl?: string; /** Optional attribution URL for front image (e.g. source/license link) */ frontImageAttribution?: string; /** Optional attribution URL for rear image (e.g. source/license link) */ rearImageAttribution?: string; /** Optional background sizing for device images */ imageFit?: DeviceImageFit; /** Optional background position for device images */ imagePosition?: string; /** Optional background repeat for device images */ imageRepeat?: DeviceImageRepeat; /** When true, stretch device image to fill the device bounds (overrides imageFit) */ stretchToFit?: boolean; } /** * Explicit handle placement for a device/PDU port. * @public */ interface PortPosition { /** * Handle side on the node. When the offset is omitted, ports on the same * side and face are distributed automatically across groups. */ side?: "top" | "right" | "bottom" | "left"; /** Side offset as percentage (0-100) */ offsetPercent?: number; /** Side offset in pixels */ offsetPx?: number; /** Absolute X position as percentage (0-100) of the owning face frame (element centre). Requires `yPercent`. */ xPercent?: number; /** Absolute Y position as percentage (0-100) of the owning face frame (element centre). Requires `xPercent`. */ yPercent?: number; /** * Authored element width as a percentage (0-100) of the owning face frame. * * Contractual: percent-based geometry is the render contract shared by ports, * cages, and bays across every surface (2D elevation, 3D, faceplate). Paired * with `heightPercent` it is the element's bounding box, and because it is * frame-relative it survives image rescaling. */ widthPercent?: number; /** * Authored element height as a percentage (0-100) of the owning face frame. * Contractual — see {@link PortPosition.widthPercent}. */ heightPercent?: number; } /** * Authoring input for port/bay geometry: the canonical {@link PortPosition} * object, or a semantic edge string such as `'left-bottom'` that * {@link normalizePortPositionInput} expands. Renderers always normalize * before reading fields. * @public */ type PortPositionInput = PortPosition | string; /** * IEC 60320 appliance couplers modelled by the renderer and the power * validation mate table. Inlets are even-numbered, connectors odd. * @public */ type PowerConnectorType = "C13" | "C14" | "C15" | "C16" | "C19" | "C20" | "C21" | "C22"; /** * Recommended simple port input for device and PDU rendering. * Pass a flat array in `ports`; `react-networks` groups entries into front/rear * `PortBlock[]` internally using each port's `face` and `group`. * @public */ interface DevicePort { /** Stable handle identifier override (defaults to `group + label`, or `label` for power) */ id?: string; /** Display label for the port */ label: string; /** Front/rear device face. `back` is accepted as an alias for `rear`. */ face?: DeviceFace | "back"; /** Optional block/group name (for example `Network Ports`, `QSFP28`, `Power Ports`) */ group?: string; /** Optional source/detected family label used for visual kind inference */ sourceTypeLabel?: string; /** Whether the port is currently connected */ connected?: boolean; /** Type of port for styling and validation */ type?: PortType; /** Cable type for connection validation */ cableType?: PortCableType; /** Optional power connector type for rendering (mainly for PDU ports) */ connectorType?: PowerConnectorType; /** Optional compatibility keys. When omitted, defaults are derived from type/cable/connector data. */ compatibility?: string[]; /** Optional sort order within a face/group bucket */ order?: number; /** * Optional placement hint. * Use `side` with `offsetPercent`/`offsetPx` for edge-anchored placement, * or `xPercent`/`yPercent` for exact coordinates. * With no resolvable placement, the renderer distributes ports across the * whole face, including ports from other groups. A lone `xPercent` or * `yPercent` is incomplete and uses that automatic placement. * Semantic edge strings (e.g. `'left-bottom'`) are also accepted and * normalized by the renderer. */ position?: PortPositionInput; } interface Port { /** Stable handle identifier override (defaults to `label`) */ id?: string; /** Display label for the port */ label: string; /** Optional source/detected family label used for visual kind inference */ sourceTypeLabel?: string; /** Whether the port is currently connected */ connected: boolean; /** Type of port for styling and validation */ type?: PortType; /** Cable type for connection validation */ cableType?: PortCableType; /** Optional power connector type for rendering (mainly for PDU ports) */ connectorType?: PowerConnectorType; /** Optional compatibility keys. When omitted, defaults are derived from type/cable/connector data. */ compatibility?: string[]; /** Optional explicit handle placement (object or semantic edge string) */ position?: PortPositionInput; } /** * Group of related ports on a device * @public */ interface PortBlock { /** Name of the port group */ name: string; /** Array of ports in this group */ ports: Port[]; } /** * Containable bay classification. Mirrors dc_designer `bay_kind`. * * A bay HOLDS a field-replaceable unit (drive, PSU, fan, line card, …) and — * unlike a port — never mounts a cable handle. Transceiver cages are the one * capability overlap (containable AND connectable): they are authored as * ports with `bay` metadata (see `TemplatePort`) so the frozen handle-id * grammar and cable endpoints survive optic swaps, and therefore do NOT appear * as a `bayKind` value here — `'transceiver_cage'` lives on `TemplatePort.bay`. * * @public */ type TemplateBayKind = "storage_bay" | "psu_bay" | "fan_bay" | "pcie_slot" | "linecard_slot" | "supervisor_slot" | "fabric_slot" | "io_slot" | "other"; /** * Occupancy/health of a single bay instance. * `predicted` marks a modelled (not yet observed) state. * @public */ type DeviceBayStatus = "ok" | "failed" | "predicted"; /** * Per-bay instance state, keyed by bay id on node data. Rides on node data * alongside `handleSideMap`; the renderer paints occupancy/failed treatment * from it. * @public */ interface DeviceBayInstanceState { /** Whether the bay currently holds a unit. */ occupied?: boolean; /** Health/occupancy status driving the bay marker's visual treatment. */ status?: DeviceBayStatus; } /** * A per-slot sub-rectangle inside a bay (e.g. one socket in a DIMM bank, one * drive position in a carrier). Geometry uses the same `PortPosition` percent * contract as ports and bays. * @public */ interface DeviceBaySlot { /** Stable identifier for the slot (unique within its bay). */ id: string; /** Human-readable label. */ label: string; /** Slot centre + bounding box as percentages of the owning face frame. */ position?: PortPosition; } /** * Containable-only element on a device face: the renderer draws an outline + * label for it but never mounts a React Flow handle. The node-data analogue of * the template `TemplateBay`; `face` selects the owning face (default * front, `back` accepted as an alias for `rear`). * @public */ interface DeviceBay { /** Stable identifier for the bay (unique within the device). */ id: string; /** Human-readable label drawn on the bay outline. */ label: string; /** Bay classification (drives visual treatment and click payloads). */ bayKind: TemplateBayKind; /** Front/rear device face. `back` is accepted as an alias for `rear`. */ face?: DeviceFace | "back"; /** Bay centre + bounding box as percentages of the owning face frame. */ position?: PortPosition; /** Optional per-slot sub-rectangles. */ slots?: DeviceBaySlot[]; } /** * Network node types supported by the diagram * @public */ type NetworkNodeType = "rack" | "switch" | "router" | "server" | "fiber" | "patch-panel" | "device" | "vertical-pdu" | "distribution-board" | "splice" | "splice-tray" | "tube" | "cable" | "multi-tube-cable" | "coupler" | "closure" | "fibre-split" | "fibre-flow-cable" | "fibre-flow-closure"; /** * Device status states * @public */ type DeviceStatus = "active" | "inactive" | "maintenance"; /** * Device face orientations * @public */ type DeviceFace = "front" | "rear"; /** * Rack rendering layout modes. * @public */ type RackLayoutMode = "single-face" | "split-face"; /** * Rack mounting behavior for a device. * @public */ type RackMountMode = "front" | "rear" | "both"; /** * Power port side configuration * @public */ type PowerSide = "left" | "right"; /** * U numbering direction for racks * @public */ type UNumberingDirection = "bottom-up" | "top-down"; /** * Shared node data fields available across node types. * Specific node kinds can narrow these fields via `NetworkNodeDataByType`. * @public */ interface NetworkNodeDataBase extends DeviceImageOptions { /** Display label for the node */ label: string; /** Current status of the node/device */ status?: DeviceStatus | string; /** Simple flat port input or grouped port blocks. Use `portGroups` / `rearPortGroups` for explicit grouped control. */ ports?: DevicePort[] | PortBlock[] | number; /** Advanced grouped front port input */ portGroups?: PortBlock[]; /** Advanced grouped rear port input */ rearPortGroups?: PortBlock[]; /** Grouped rear port blocks (rack JSON alias for `rearPortGroups`) */ rearPorts?: PortBlock[]; /** List of connected node IDs */ connections?: string[]; /** NetBox integration ID */ netboxId?: number | string; /** NetBox object type */ netboxType?: "device" | "rack" | "interface" | "cable" | string; /** Inventory integration ID */ inventoryId?: number | string; /** Inventory object type */ inventoryType?: "device" | "rack" | "interface" | "cable" | string; /** Rack height in U units */ uHeight?: number; /** Device position within rack in U units */ uPosition?: number; /** Whether this node is currently mounted inside a rack container */ isRackMounted?: boolean; /** Front/rear orientation for devices and rack faces */ face?: DeviceFace; /** Rack rendering layout mode */ rackLayout?: RackLayoutMode; /** Gap in pixels between front and rear faces in split-face mode */ rackFaceGapPx?: number; /** Device mount behavior within a rack */ mountMode?: RackMountMode; /** Device type specification */ deviceType?: string; /** * When false, device elevation renders as a status-colored block without front/rear photos. * Defaults to true (show photos when URLs exist). */ showDeviceImages?: boolean; /** Device manufacturer */ manufacturer?: string; /** Device role in network */ role?: string; /** Device width configuration */ width?: Width | number; /** Power port side for rear face */ powerSide?: PowerSide; /** Vertical PDU height in centimeters */ heightCm?: number; /** Number of AC power ports */ powerPorts?: number; /** Optional explicit PDU connector sequence */ portTypes?: Array<"C13" | "C19">; /** Optional grouped PDU ports (supports custom positions/types) */ pduPortGroups?: PortBlock[]; /** Vertical PDU width in pixels */ widthPx?: number; /** Optional management unit position for vertical PDUs */ mgmt_unit?: "top" | "middle" | "bottom"; /** U numbering direction for rack nodes */ uNumberingDirection?: UNumberingDirection; /** Custom header text for rack nodes */ customHeaderText?: string; /** Rack UI marker visibility */ showUMarkers?: boolean; /** Holder position within tray (1-12) for splice nodes */ holderPosition?: number; /** Loss value in dB for splice nodes */ lossDb?: number; /** Splice mode */ mode?: "single" | "ribbon"; /** Legacy ribbon flag */ ribbon?: boolean; /** Ribbon fiber IDs */ ribbonFiberIds?: number[]; /** Connector type for coupler nodes */ connector?: "SC" | "LC"; /** Number of fibers for coupler nodes (1, 2, or 4) */ couplerFiberCount?: 1 | 2 | 4; /** Optional port labels for left side of coupler */ portLabelsLeft?: string[]; /** Optional port labels for right side of coupler */ portLabelsRight?: string[]; /** When true, coupler output (right) ports inherit left-side fiber color instead of default yellow. */ passThroughColor?: boolean; /** Slot position for couplers inside panels (1-based, vertical slots aligned to right edge) */ slotPosition?: number; /** Width override for panel-like container nodes */ panelWidth?: number; /** Height override for panel-like container nodes */ panelHeight?: number; /** Width override for closure nodes */ closureWidth?: number; /** Height override for closure nodes */ closureHeight?: number; /** Optional rack width in pixels (for rack nodes, default: 300px) */ rackWidthPx?: number; /** Number of rows for container nodes (patch-panel, closure) */ rows?: number; /** Number of columns for container nodes (patch-panel, closure) */ cols?: number; /** Number of trays for closure nodes */ trayCount?: number; /** Header text for container nodes */ header?: string; /** Type of fibre splitter: 'splitter' or 'WDM' (default: 'splitter') */ splitterType?: "splitter" | "WDM"; /** Number of input fibers on the left (1 or 2, default: 1) */ inputCount?: number; /** Number of output fibers on the right (1-64, default: 8) */ outputCount?: number; /** Tube index (1-based) */ tubeIndex?: number; /** Tube count for multi-tube cables */ tubeCount?: number; /** Tube start index for multi-tube cables */ tubeStartIndex?: number; /** Number of fibers per tube */ fibersPerTube?: number; /** Total fiber count for cables */ fiberCount?: number; /** Cable identifier */ cableId?: string; /** Primary node color override */ color?: string; /** Rotation in degrees for rotatable nodes */ rotation?: number; /** Tube handle orientation */ startOn?: "left-center" | "left" | "right"; /** Rack metadata for integrations */ facilityId?: string | number | null; /** Rack serial metadata */ serial?: string | null; /** Asset tag metadata */ assetTag?: string | null; /** Site metadata */ site?: string; /** Tenant metadata */ tenant?: string; /** Primary IPv4 metadata */ primaryIp4?: string; /** Primary IPv6 metadata */ primaryIp6?: string; /** Rack name metadata */ rack?: string | number | null; /** Optional arrays used by inventory/netbox transforms */ racks?: unknown[]; devices?: unknown[]; cables?: unknown[]; /** UI color mode metadata */ colorMode?: "light" | "dark" | "system"; /** Generic dimensions used by some helpers */ height?: number; headerHeight?: number; /** Optional precomputed map for handle-to-face resolution */ handleSideMap?: Record; /** * Per-bay instance state keyed by bay id (occupancy/health). Rides on node * data alongside `handleSideMap`; DeviceNode paints bay markers from it. */ bayState?: Record; /** Additional extension metadata */ metadata?: Record; } /** * Rack node data. * @public */ interface RackNodeData extends NetworkNodeDataBase { ports?: number; } /** * What kind of power-distribution equipment a `vertical-pdu` node stands for. * The renderer draws them all as a vertical strip; the label is carried so * consumers and validation can tell a rack PDU from an RPP, a busway tap, or a * sub-panel. * @public */ type PduBoardType = "pdu" | "rpp" | "panel" | "busway" | "other"; /** Supply family of a PDU strip. @public */ type PduSupply = "ac" | "dc"; /** * A/B designation of the branch circuit feeding a PDU. `primary` is the A * feed, `secondary` the B feed; redundancy rules read it to tell the two * halves of a 2N design apart. * @public */ type PowerFeedType = "primary" | "secondary"; /** * Which half of an IEC 60320 / IEC 60309 pairing a connector is. Inlets on * equipment are male (pins); cord connectors are female (sockets). * @public */ type PowerConnectorGender = "male" | "female"; /** * Vertical PDU node data. * * Everything here is optional and additive — a PDU authored before the inlet * model (label + `powerPorts` + `portTypes`) renders and validates exactly as * it did, and the inlet handle is not mounted at all unless inlet data is * present. * * The strip has two electrically distinct sides: * * - the **inlet** — where a branch circuit from a distribution-board breaker * way lands (fixed wiring: IEC 60309, hardwired, C20, NEMA locking). One per * strip, handle id `inlet`. * - the **outlets** — where equipment cords land, handle ids `"1"…"N"` * top-down under IEC 60320 mate rules. * * **Reserved handle ids.** `inlet` (and `incomer`, the distribution-board * spelling) name the supply inlet. Do not give an outlet in `pduPortGroups` an * `id` or `label` that lowercases to either: the strip would mount two handles * with the same id. A declared outlet deliberately wins that collision — it * classifies as a cord source, not as the supply inlet, so the cords it carries * still validate — but the inlet handle then becomes unreachable. Number the * outlets, or give them a distinct prefix (`rear-power-1`). * @public */ interface VerticalPduNodeData extends NetworkNodeDataBase { /** * Free-text inlet connector designation, e.g. `"IEC 60309 32A"`, * `"C20"`, `"NEMA L6-30P"`, `"hardwired"`. Free text because the inlet * families a rack PDU can carry are regional and open-ended; the connector * *mate* rules only apply to the IEC 60320 cord side (the outlets). */ inletConnector?: string; /** Inlet current rating in amps (the branch-circuit rating the strip takes). */ inletAmps?: number; /** Inlet gender — equipment inlets are normally `male`. */ inletGender?: PowerConnectorGender; /** A/B designation of the feed landing on the inlet. */ feedType?: PowerFeedType; /** What kind of distribution equipment this strip stands for. */ boardType?: PduBoardType; /** Supply family. */ supply?: PduSupply; /** Nominal supply voltage in volts (integer, e.g. 230). */ voltage?: number; /** Supply phase count. Outlets are attributed round-robin across it. */ phases?: 1 | 3; /** * Rating in amps of the strip's own outlet/bank overcurrent protection * (internal breakers or fuses), when it has any. PWR-A06 judges the cords * below a strip that declares it against this rating instead of the upstream * way's. */ outletProtectionA?: number; /** Optional equipment name, distinct from the drawn `label`. */ name?: string; } /** * Device-like node data (servers/switches/routers/generic device). * @public */ interface DeviceNodeData extends NetworkNodeDataBase { ports?: DevicePort[] | PortBlock[] | number; /** * Containable-only bays drawn as outlines + labels (never cable handles). * Each bay's `face` selects the owning face (default front). */ bays?: DeviceBay[]; /** * Nameplate/maximum power draw in **watts**. Named after NetBox's * `DeviceType.airflow`-adjacent power fields (`maximum_draw`), which are watts * — keep the unit in watts so a NetBox sync is a straight field copy. */ maximumDrawW?: number; /** * Allocated (design/budgeted) power draw in **watts**. NetBox's * `allocated_draw`; used by load rules to sum a board way's committed load. */ allocatedDrawW?: number; /** * How many power feeds this device is expected to have (NetBox models this as * redundant power ports). `2` marks an A+B device, so losing one feed is * `degraded` rather than unpowered. */ expectedFeeds?: 1 | 2; } /** * Switch state of a single breaker way. * @public */ type BreakerSwitchState = "closed" | "open" | "tripped"; /** * Phase label carried by a breaker way. Purely a label — the library does not * model three-phase electrically (see PRD workstream C non-goals). * @public */ type BreakerPhase = "L1" | "L2" | "L3" | "3P"; /** * One breaker way (slot) on a distribution board. A way is not its own node in * the physical view: it is a connection endpoint on the board, mounting exactly * one power handle. * @public */ interface BreakerWay { /** Stable identifier for the way (unique within the board). */ id: string; /** Human-readable label drawn on the way row (e.g. `1`, `L1-3`). */ label: string; /** Pole count (1 = single-pole, 3 = three-pole). */ poles?: number; /** Breaker rating in amps. */ ratingA?: number; /** Phase label. `3P` (or `poles: 3`) marks a three-phase way. */ phase?: BreakerPhase; /** * Circuit voltage this way supplies, overriding the board's: line-to-neutral * for a single-pole way, line-to-line for a 2-pole or three-phase way. */ voltageV?: number; /** * Optional explicit placement as percentages of the board frame. Omitted ways * are auto-laid-out in the generated faceplate grid, which is the normal case. */ position?: PortPosition; } /** * Per-way instance state keyed by way id, mirroring {@link DeviceBayInstanceState}. * @public */ interface BreakerWayInstanceState { /** Whether the breaker is closed, deliberately open, or tripped. */ switchState: BreakerSwitchState; /** Optional health status, reusing the bay status vocabulary. */ status?: DeviceBayStatus; } /** * Distribution board node data. Boards are free-floating by default; set * {@link DistributionBoardNodeData.rackMountable} to opt a board into * rack assignment. * @public */ interface DistributionBoardNodeData extends NetworkNodeDataBase { /** The board's breaker ways, rendered top-to-bottom in column order. */ ways: BreakerWay[]; /** Per-way switch/health state keyed by way id. */ wayState?: Record; /** * Nominal board voltage in volts — the legacy single figure. When neither * {@link DistributionBoardNodeData.phaseVoltageV} nor * {@link DistributionBoardNodeData.lineToLineVoltageV} is set, the load rules * (PWR-B01/B02) use it unchanged for every way: as the line-to-neutral * voltage of single-pole ways and the line-to-line voltage of 2-pole / * three-phase ways. That is only right when all the board's ways are one * kind (PWR-B03 flags boards where it cannot be); declare the explicit pair * for a mixed board. */ voltageV?: number; /** * Nominal **line-to-neutral** (phase) voltage in volts — what a single-pole * way supplies (`230` on a 230/400 V board, `120` on 120/208 V, `277` on * 277/480 V). Defaults to `lineToLineVoltageV / √3` when only that is set. */ phaseVoltageV?: number; /** * Nominal **line-to-line** voltage in volts — what a 2-pole or three-phase * way supplies (`400`, `208`, `480`). Defaults to `phaseVoltageV × √3` when * only that is set. With no voltage declared at all the rules assume * 120/208 V under `NEC` and 230/400 V under `IEC` (and PWR-B03 says so). */ lineToLineVoltageV?: number; /** * Power factor (0–1] the load rules apply when converting nameplate watts to * amps. Defaults to 1 (watts treated as volt-amperes, NetBox's convention). */ powerFactor?: number; /** * What kind of distribution asset this board is. Drives the header badge * only — an `rpp` is drawn `RPP`, a `busway` `BUSWAY`, and anything else * (including omitted) falls back to `DB`. Purely a labelling concern: every * board type shares one electrical model of ways and an incomer. */ boardType?: PduBoardType; /** * Rating of the board's incomer/main device in amps, shown in the header. * Distinct from a way's `ratingA`: this is the device feeding the busbar, * not one of the outgoing ways. */ incomerRatingA?: number; /** Which code vocabulary consumer rules should read this board under. */ codeMode?: "NEC" | "IEC"; /** * Continuous-load derate ceiling as a percentage of a way's rating. Defaults * by `codeMode`: 80 under `NEC` (the default mode), 100 under `IEC`. */ maxUtilization?: number; /** * Opt-in flag marking this board as rack-mountable. `distribution-board` is * deliberately NOT in `RACK_ASSIGNABLE_NODE_TYPES` — boards are wall-mounted * free-floating nodes by default, and this flag is the hook for the * rack-mounted minority. */ rackMountable?: boolean; /** Number of way columns in the generated faceplate (default 1). */ wayColumns?: number; } /** * Fibre flow cable node data. * @public */ interface FibreFlowCableNodeData extends NetworkNodeDataBase { cable: FibreFlowCable; side: "left" | "right"; rowHeight: number; columnWidth: number; showTubeLabels: boolean; showFiberNumbers: boolean; layout: unknown; colorMode?: "dark" | "light"; } /** * Fibre flow closure node data. * @public */ interface FibreFlowClosureNodeData extends NetworkNodeDataBase { width?: number; height?: number; headerHeight?: number; colorMode?: "dark" | "light"; } /** * Mapping from node type to corresponding data type. * @public */ interface NetworkNodeDataByType { rack: RackNodeData; switch: DeviceNodeData; router: DeviceNodeData; server: DeviceNodeData; fiber: NetworkNodeDataBase; "patch-panel": NetworkNodeDataBase; device: DeviceNodeData; "vertical-pdu": VerticalPduNodeData; "distribution-board": DistributionBoardNodeData; splice: NetworkNodeDataBase; "splice-tray": NetworkNodeDataBase; tube: NetworkNodeDataBase; cable: NetworkNodeDataBase; "multi-tube-cable": NetworkNodeDataBase; coupler: NetworkNodeDataBase; closure: NetworkNodeDataBase; "fibre-split": NetworkNodeDataBase; "fibre-flow-cable": FibreFlowCableNodeData; "fibre-flow-closure": FibreFlowClosureNodeData; } /** * Network node structure with data discriminated by `type`. * @public */ type NetworkNode = TType extends NetworkNodeType ? Node, TType> & { /** Type of network node */ type: TType; /** Node data and configuration */ data: NetworkNodeDataByType[TType] & TExtra; } : never; /** * Network edge types * @public */ type NetworkEdgeType = "fiber" | "ethernet" | "power" | "smoothstep" | "step" | "thick-cable" | "fibre-flow" | "fibre-flow-link"; /** * Edge data payload. * @public */ interface NetworkEdgeData { /** * Index signature so this data satisfies `@xyflow/react` v12's `Edge` * constraint (`Record`). Edge data is never `Omit`-ed, so * (unlike the node data types) an index signature is safe here. */ [key: string]: unknown; /** Connection bandwidth */ bandwidth?: string; /** * Cable length, in the source system's unit (see {@link NetworkEdgeData.lengthUnit}). * Unit-less: prefer {@link NetworkEdgeData.lengthCm} for comparisons. */ length?: number; /** Unit of {@link NetworkEdgeData.length} as the source system reported it (e.g. `m`, `ft`). */ lengthUnit?: string; /** * Cable length normalised to centimetres. The NetBox/inventory converters set * it when the source length has a known unit; PWR-A12 reads it in preference * to the unit-less `length`. */ lengthCm?: number; /** Edge color for styling */ color?: string; /** Edge kind for styling/validation */ kind?: "fiber" | "power" | "network"; /** Whether this edge represents a ribbon fiber connection */ isRibbon?: boolean; /** Array of fiber IDs for ribbon mode (6-12 fibers) */ ribbonFiberIds?: number[]; /** Highlight edge with a pulsing stroke */ highlight?: boolean; /** Override highlight color (defaults to edge color) */ highlightColor?: string; /** Override highlight max stroke width */ highlightWidth?: number; /** Optional tag for grouping edges in demos */ traceTag?: string; /** Legacy striped edge flag */ striped?: boolean; /** Cable type metadata used by demos/helpers */ cableType?: PortCableType; /** NetBox integration metadata */ netboxId?: number | string; netboxType?: "device" | "rack" | "interface" | "cable" | string; /** Inventory integration metadata */ inventoryId?: number | string; inventoryType?: "device" | "rack" | "interface" | "cable" | string; /** Status metadata */ status?: string; /** Endpoint metadata */ terminationA?: string; terminationB?: string; /** Optional display label for the edge */ label?: string; /** Optional opacity for styling (0–1) */ opacity?: number; /** Optional power edge stroke width override */ powerStrokeWidth?: number; /** Optional power edge stroke dasharray override */ powerStrokeDasharray?: string; /** Optional power edge opacity override (0–1) */ powerOpacity?: number; /** * Power energisation overlay: `true` renders the edge as live (marching * dashes), `false` renders it dimmed/grey. Omit to keep the classic * (unaware) power edge styling. Produced by `computeEnergization`. */ energized?: boolean; /** * Direction power travels across the edge, relative to its own endpoints. * Draws a flow arrow on an energised edge; ignored otherwise. */ flowDirection?: "source-to-target" | "target-to-source"; /** Additional extension metadata */ metadata?: Record; } /** * Network edge data structure * @public */ type NetworkEdge = { /** Unique identifier for the edge */ id: string; /** Source node ID */ source: string; /** Target node ID */ target: string; /** Source handle/port ID */ sourceHandle?: string; /** Target handle/port ID */ targetHandle?: string; /** Type of network connection */ type?: NetworkEdgeType; /** Whether the edge should be hidden from rendering */ hidden?: boolean; /** * Whether the edge may be deleted by user interaction (keyboard Delete, * batch delete). Mirrors React Flow's `Edge.deletable`; defaults to true. * Deletion programmatically through `edges` prop updates is unaffected. */ deletable?: boolean; /** * Width (px) of the invisible interaction stroke rendered beneath the edge, * forwarded to React Flow's `Edge.interactionWidth`. It widens the edge's * click/hover target, but the stroke also sits above neighboring node * handles in z-order — an oversized value can occlude nearby ports and make * them unreachable for connection drops in dense layouts. When omitted, the * diagram's `edgeInteractionWidth` default applies. */ interactionWidth?: number; /** Edge data and configuration */ data?: TData; }; /** * Canonical persisted/editor document schema independent from React Flow handle ids. * Prefer this model for saving diagrams, syncing external systems, and controlled * document-mode usage via `document` / `onDocumentChange`. * @public */ interface DiagramDocument { /** * Document schema version. Always `1` for documents emitted by this library. * A missing version on input is treated as legacy v0 (identical to `1` today); * a version greater than `1` is parsed best-effort with a console warning. */ version: 1; nodes: DiagramNode[]; edges: DiagramEdge[]; ui?: DiagramUiState; metadata?: Record; } /** * Node kinds used by the document model. * @public */ type DiagramNodeKind = "rack" | "equipment" | "pdu" | "distribution-board" | "fiber" | "tube" | "cable" | "multi-tube-cable" | "splice" | "coupler" | "splitter" | "container" | "fibre-flow-cable" | "fibre-flow-closure"; /** * Placement data for document nodes. * @public */ interface DiagramNodePlacement { position: { x: number; y: number; }; parentId?: string; extent?: "parent"; rack?: { uPosition?: number; mountMode?: RackMountMode; rackLayout?: RackLayoutMode; rackWidthPx?: number; rackFaceGapPx?: number; }; container?: { slotPosition?: number; holderPosition?: number; }; } /** * Endpoint definition for document nodes. * @public */ interface DiagramEndpoint { /** * Opaque unique key for this endpoint within its document. The shipped * adapters mint handle-grammar strings here for render-side stability, but * consumers may supply any unique string — the reverse adapter resolves * edges through the endpoint RECORD, so renaming a port's `label` does not * require re-keying when ids are consumer-minted. Do not parse this value. * * When a device mounts the same port id on both faces, the shipped forward * adapter mints the rear endpoint as `--rear` (the renderer's split-face * handle alias) so ids stay unique; the reverse adapter gives the rebuilt rear * port back its shared ``. */ id: string; label: string; face?: DeviceFace | "internal"; group?: string; role?: "network" | "power" | "fiber" | "tube" | "splice" | "coupler" | "splitter" | "cable" | "generic"; medium?: "ethernet" | "fiber" | "power" | "tube" | "generic"; type?: PortType; cableType?: PortCableType; connector?: string; /** * Free-text source-of-truth port type label (e.g. `"QSFP28"`, `"RJ45"`) used * to pick the port's connector visual. Preserved verbatim across the document * round-trip so a port keeps its icon. */ sourceTypeLabel?: string; compatibility?: string[]; layout?: PortPosition; } /** * Render-focused node data for the document model. * @public */ interface DiagramNodeRender { status?: DeviceStatus | string; face?: DeviceFace; width?: Width | number; widthPx?: number; height?: number; header?: string; color?: string; colorMode?: "light" | "dark" | "system"; rackWidthPx?: number; rackFaceGapPx?: number; images?: DeviceImageOptions; dimensions?: Record; showUMarkers?: boolean; customHeaderText?: string; powerSide?: PowerSide; rotation?: number; } /** * External reference attached to a document node. * @public */ interface DiagramExternalRef { source: "netbox" | "inventory" | string; id: string | number; type?: string; metadata?: Record; } /** * Document node. * @public */ interface DiagramNode { id: string; kind: DiagramNodeKind; subtype?: string; label: string; placement: DiagramNodePlacement; endpoints?: DiagramEndpoint[]; render?: DiagramNodeRender; config?: Record; externalRefs?: DiagramExternalRef[]; metadata?: Record; } /** * Endpoint reference used by document edges. * @public */ interface DiagramEdgeEndpoint { nodeId: string; endpointId?: string | null; } /** * Document edge. * @public */ interface DiagramEdge { id: string; source: DiagramEdgeEndpoint; target: DiagramEdgeEndpoint; type?: NetworkEdgeType; hidden?: boolean; /** Mirrors {@link NetworkEdge.deletable}; omitted when the runtime edge left it unset. */ deletable?: boolean; /** Mirrors {@link NetworkEdge.interactionWidth}; omitted when unset. */ interactionWidth?: number; data?: NetworkEdgeData; metadata?: Record; } /** * Non-topology UI state stored alongside a document. * @public */ interface DiagramUiState { nodeState?: Record; }>; metadata?: Record; } /** * Rack device types * @public */ type RackDeviceType = "server" | "switch" | "router" | "patch-panel" | "ups"; /** * Rack configuration structure * @public */ interface RackConfig { /** Unique rack identifier */ id: string; /** Rack display name */ name: string; /** Rack position coordinates */ position: { x: number; y: number; }; /** Rack height in U units */ units: number; /** U numbering direction (default: 'bottom-up') */ uNumberingDirection?: UNumberingDirection; /** Custom header text for rack */ customHeaderText?: string; /** Rack rendering layout mode */ rackLayout?: RackLayoutMode; /** Gap in pixels between front and rear faces in split-face mode */ rackFaceGapPx?: number; /** Devices mounted in the rack */ devices: RackDevice[]; /** Optional rack width in pixels (default: 300px which represents standard 48.26cm/19" rack) */ rackWidthPx?: number; } /** * Device mounted in a rack * @public */ interface RackDevice extends DeviceImageOptions { /** Unique device identifier */ id: string; /** Device display name */ name: string; /** Starting U position in rack */ unit: number; /** Device height in U units */ height: number; /** Device type */ type: RackDeviceType; /** Device width configuration */ width?: Width; /** Device mount behavior within a rack */ mountMode?: RackMountMode; /** Device role in network */ role?: string; /** Recommended simple port input (flat `DevicePort[]` or grouped `PortBlock[]`). */ ports?: DevicePort[] | PortBlock[]; /** Current status of the device */ status?: DeviceStatus | string; /** Advanced grouped front port input */ portGroups?: PortBlock[]; /** Advanced grouped rear port input */ rearPortGroups?: PortBlock[]; /** Grouped rear port blocks (rack JSON alias for `rearPortGroups`) */ rearPorts?: PortBlock[]; /** Power port side for rear face */ powerSide?: PowerSide; /** * Containable-only bays drawn as outlines + labels (never cable handles). * Each bay's `face` selects the owning face (default front). * * Passed straight through to the device node's own `bays` node-data field, so * authoring bays here is equivalent to authoring them on node data — hosts * building from `rackConfig.devices[]` no longer need the per-device extra * node-data channel just to render bays. */ bays?: DeviceBay[]; /** Connected device IDs */ connections?: string[]; } export { type NetworkEdgeData as A, type BreakerPhase as B, type NetworkEdgeType as C, type DiagramDocument as D, type NetworkNodeDataByType as E, type NetworkNodeType as F, type PduBoardType as G, type PduSupply as H, type PortPositionInput as I, type PortType as J, type PowerConnectorGender as K, type PowerFeedType as L, type PowerSide as M, type NetworkNode as N, type RackDevice as O, type Port as P, type RackLayoutMode as Q, type RackConfig as R, type RackMountMode as S, type TemplateBayKind as T, type UNumberingDirection as U, type VerticalPduNodeData as V, Width as W, type PowerConnectorType as X, type NetworkEdge as a, type DiagramNodeKind as b, type DevicePort as c, type DeviceFace as d, type PortBlock as e, type NetworkNodeDataBase as f, type PortCableType as g, type PortPosition as h, type DiagramNode as i, type DiagramEdge as j, type DiagramUiState as k, type BreakerSwitchState as l, type BreakerWay as m, type BreakerWayInstanceState as n, type DeviceBay as o, type DeviceBayInstanceState as p, type DeviceBaySlot as q, type DeviceBayStatus as r, type DeviceImageOptions as s, type DeviceStatus as t, type DiagramEdgeEndpoint as u, type DiagramEndpoint as v, type DiagramExternalRef as w, type DiagramNodePlacement as x, type DiagramNodeRender as y, type DistributionBoardNodeData as z };