Port

API reference for the Port class

Port

The Port class represents a connection point on a node. Ports are where connections begin and end, defining how nodes can be linked together.

Constructor

const Port({
  required String id,
  required String name,
  bool multiConnections = false,
  PortPosition position = PortPosition.left,
  Offset offset = Offset.zero,
  PortType type = PortType.both,
  MarkerShape? shape,
  Size? size,
  String? tooltip,
  bool isConnectable = true,
  int? maxConnections,
  bool showLabel = false,
})

Properties

PropertyTypeDefaultDescription
idStringrequiredUnique identifier within the node
nameStringrequiredDisplay label
multiConnectionsboolfalseWhether multiple connections are allowed
positionPortPositionleftSide of the node
offsetOffsetOffset.zeroPosition offset for precise placement
typePortTypebothDirection: source, target, or both
shapeMarkerShape?nullVisual shape (falls back to theme)
sizeSize?nullPort dimensions (falls back to theme)
tooltipString?nullTooltip text on hover
isConnectablebooltrueWhether connections can be made
maxConnectionsint?nullMaximum connections (null = unlimited)
showLabelboolfalseWhether to display the port's label

PortPosition

Where the port appears on the node:

PositionDescription
PortPosition.leftLeft edge (default)
PortPosition.rightRight edge
PortPosition.topTop edge
PortPosition.bottomBottom edge

Input ports are typically on the left, output ports on the right. But you can place them anywhere.

PortType

Direction of data flow for the port:

TypeDescription
PortType.sourceOutput only - can emit connections
PortType.targetInput only - can receive connections
PortType.bothBidirectional - can both emit and receive (default)

Computed Properties

PropertyTypeDescription
isSourceboolWhether this port can act as a source (output)
isTargetboolWhether this port can act as a target (input)

Port Offset

The offset property controls precise port positioning within the node.

For left/right ports:

  • offset.dy specifies the vertical center position (distance from top)
  • offset.dx adjusts horizontal position from the edge

For top/bottom ports:

  • offset.dx specifies the horizontal center position (distance from left)
  • offset.dy adjusts vertical position from the edge

Example for a 150x100 node:

// Right port centered vertically at 50 (middle of node)
Port(id: 'out', name: 'Output', position: PortPosition.right, offset: Offset(0, 50))

// Top port centered horizontally at 75 (middle of node width)
Port(id: 'in', name: 'Input', position: PortPosition.top, offset: Offset(75, 0))

// Two right ports at 1/3 and 2/3 height
Port(id: 'out1', name: 'Out 1', position: PortPosition.right, offset: Offset(0, 33))
Port(id: 'out2', name: 'Out 2', position: PortPosition.right, offset: Offset(0, 67))

Examples

final node = Node<MyData>(
  id: 'node-1',
  type: 'process',
  position: Offset(100, 100),
  data: MyData(),
  inputPorts: [
    Port(id: 'in-1', name: 'Input'),
  ],
  outputPorts: [
    Port(id: 'out-1', name: 'Output', position: PortPosition.right),
  ],
);
final node = Node<ProcessData>(
  id: 'process',
  type: 'processor',
  position: Offset(100, 100),
  size: Size(180, 120),
  data: ProcessData(),
  inputPorts: [
    Port(
      id: 'data-in',
      name: 'Data',
      position: PortPosition.left,
      showLabel: true,
    ),
    Port(
      id: 'config-in',
      name: 'Config',
      position: PortPosition.top,
      showLabel: true,
    ),
  ],
  outputPorts: [
    Port(
      id: 'result-out',
      name: 'Result',
      position: PortPosition.right,
      showLabel: true,
    ),
    Port(
      id: 'error-out',
      name: 'Error',
      position: PortPosition.bottom,
      showLabel: true,
    ),
  ],
);
final node = Node<TypedData>(
  id: 'typed-node',
  type: 'typed',
  position: Offset(100, 100),
  size: Size(200, 100),
  data: TypedData(),
  inputPorts: [
    Port(
      id: 'string-in',
      name: 'String',
      type: PortType.target,
      multiConnections: true,
      maxConnections: 5,
      tooltip: 'Accepts up to 5 string connections',
    ),
    Port(
      id: 'number-in',
      name: 'Number',
      type: PortType.target,
      shape: MarkerShapes.diamond,
      size: Size(12, 12),
    ),
  ],
  outputPorts: [
    Port(
      id: 'any-out',
      name: 'Output',
      type: PortType.source,
      position: PortPosition.right,
    ),
  ],
);

Connection Limits

Control how many connections a port can have:

// Single connection only
Port(
  id: 'trigger',
  name: 'Trigger',
  multiConnections: false, // Default - one connection max
)

// Multiple connections with limit
Port(
  id: 'inputs',
  name: 'Inputs',
  multiConnections: true,
  maxConnections: 5, // Up to 5 connections
)

// Unlimited connections
Port(
  id: 'broadcast',
  name: 'Broadcast',
  multiConnections: true,
  maxConnections: null, // No limit
)

MarkerShape

Port shapes are defined using the MarkerShape abstract class. Built-in shapes are available through MarkerShapes:

// Use built-in shapes
Port(id: 'port', name: 'Port', shape: MarkerShapes.circle)
Port(id: 'port', name: 'Port', shape: MarkerShapes.diamond)
Port(id: 'port', name: 'Port', shape: MarkerShapes.triangle)
Port(id: 'port', name: 'Port', shape: MarkerShapes.square)
Port(id: 'port', name: 'Port', shape: MarkerShapes.capsuleHalf)

If no shape is specified, the port uses the shape from PortTheme.shape (default: capsuleHalf).

Methods

copyWith

Create a copy with updated properties.

Port copyWith({
  String? id,
  String? name,
  bool? multiConnections,
  PortPosition? position,
  Offset? offset,
  PortType? type,
  MarkerShape? shape,
  Size? size,
  String? tooltip,
  bool? isConnectable,
  int? maxConnections,
  bool? showLabel,
})

Example:

final updatedPort = port.copyWith(
  name: 'Updated Name',
  multiConnections: true,
);

toJson

Serialize to JSON.

Map<String, dynamic> toJson()

fromJson

Create from JSON.

factory Port.fromJson(Map<String, dynamic> json)

Port Styling

Configure port appearance through PortTheme:

NodeFlowTheme(
  portTheme: PortTheme(
    size: Size(9, 9),
    color: Colors.grey,
    connectedColor: Colors.blue,
    snappingColor: Colors.lightBlue,
    borderColor: Colors.white,
    borderWidth: 0,
    shape: MarkerShapes.capsuleHalf,
    showLabel: false,
    labelTextStyle: TextStyle(fontSize: 10),
    labelOffset: 4.0,
    labelVisibilityThreshold: 0.5,
    highlightBorderColor: Colors.black,
    highlightBorderWidthDelta: 1.5,
  ),
)
PropertyDescription
sizePort dimensions (Size, not double)
colorDefault fill color
connectedColorColor when port has connections
snappingColorColor when connection is being dragged nearby
borderColorBorder outline color
borderWidthBorder thickness
shapeDefault marker shape
showLabelGlobal label visibility
labelTextStyleText style for labels
labelOffsetDistance from port to label
labelVisibilityThresholdMinimum zoom to show labels
highlightBorderColorBorder color when highlighted
highlightBorderWidthDeltaExtra border width when highlighted

See Port Shapes and Port Labels for more styling details.

Best Practices

  1. Unique IDs: Port IDs should be unique within a node, often prefixed with node ID
  2. Clear Names: Use descriptive names that explain the port's purpose
  3. Consistent Positioning: Follow conventions (inputs left, outputs right)
  4. Type Indication: Use shapes or tooltips to indicate data types
  5. Limit Connections: Set maxConnections when appropriate
  6. Connectable Flag: Use isConnectable: false for display-only ports

On this page