# PortAwareLayoutManager

Import it from `@grafloria/engine`.

Port-aware layout computation utilities

```ts
class PortAwareLayoutManager
```

**Methods**

- `static assignPortSides( ports: PortInfo[], nodePositions: Map<string, { x: number; y: number }>, options: PortAwareLayoutOptions ): Map<string, PortSide>` (static) — Assign ports to sides of their parent nodes
- `static orderPorts( ports: PortInfo[], portAssignments: Map<string, PortSide>, nodePositions: Map<string, { x: number; y: number }>, links: Array<{ sourcePortId?: string; targetPortId?: string }>, options: PortAwareLayoutOptions ): Map<string, string[]>` (static) — Order ports on each node to minimize edge crossings
- `static calculatePortPositions( ports: PortInfo[], portAssignments: Map<string, PortSide>, portOrdering: Map<string, string[]>, nodeSizes: Map<string, { width: number; height: number }>, options: PortAwareLayoutOptions ): Map<string, { x: number; y: number; side: PortSide }>` (static) — Calculate physical port positions on nodes
- `static countEdgeCrossings( portPositions: Map<string, { x: number; y: number; side: PortSide }>, nodePositions: Map<string, { x: number; y: number }>, links: Array<{ sourcePortId?: string; targetPortId?: string }>, ports?: PortInfo[] ): number` (static) — Count edge crossings for a given port configuration.

`ports` is what makes the fix possible: it maps a port back to its node, so
the port's offset can be added to the node's origin. It is optional only for
source compatibility — without it we cannot resolve the frame, so we fall back
to the relative comparison rather than silently inventing a node position.
- `static computePortLayout( ports: PortInfo[], nodePositions: Map<string, { x: number; y: number }>, nodeSizes: Map<string, { width: number; height: number }>, links: Array<{ sourcePortId?: string; targetPortId?: string }>, options: PortAwareLayoutOptions ): PortAwareLayoutResult` (static) — Generate complete port-aware layout result
