LivePanels.Graph.Layout (livepanels v0.1.0)

Copy Markdown View Source

Headless graph layout assist contracts.

This module plans placements for graph-connected world items and returns data that applications can submit through the normal canvas place_item command path. It does not render controls, choose product workflow language, or persist layout by itself.

Summary

Functions

Returns a port-aware payload for external graph layout engines.

Converts external layout node coordinates into place_item command tuples.

Converts an external adapter result into placement tuples.

Returns place_item command tuples for a layout strategy.

Returns placements arranged by connected component.

Returns layered graph placements as {item_id, placement} tuples.

Returns placements aligned for orthogonal graph routing.

Returns a port-aware external layout adapter payload.

Returns place_item commands for tree_placements/2.

Returns tree-oriented placements for graph world items.

Types

adapter()

@type adapter() :: %{
  direction: axis(),
  nodes: [map()],
  connectors: [map()],
  components: [component()],
  boundaries: [boundary()]
}

axis()

@type axis() :: :horizontal | :vertical

boundary()

@type boundary() :: map()

component()

@type component() :: %{
  id: String.t(),
  item_ids: [String.t()],
  connector_ids: [String.t()]
}

layout_strategy()

@type layout_strategy() :: :layered | :tree | :orthogonal | :components

placement()

@type placement() :: %{
  space: :world,
  anchor: :top_left,
  x: integer(),
  y: integer(),
  w: number(),
  h: number()
}

Functions

adapter(state, opts \\ [])

@spec adapter(map(), keyword() | map()) :: adapter()

Returns a port-aware payload for external graph layout engines.

adapter_commands(state, result, opts \\ [])

@spec adapter_commands(map(), map() | [map()], keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Converts external layout node coordinates into place_item command tuples.

Accepted node result entries are maps with :id/"id" plus :x/"x" and :y/"y". Width and height default to the current item frame when absent.

adapter_placements(state, result, opts \\ [])

@spec adapter_placements(map(), map() | [map()], keyword() | map()) :: [
  {String.t(), placement()}
]

Converts an external adapter result into placement tuples.

commands(state, strategy, opts \\ [])

@spec commands(map(), layout_strategy(), keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Returns place_item command tuples for a layout strategy.

Strategies: :layered, :tree, :orthogonal, :components.

component_commands(state, opts \\ [])

@spec component_commands(map(), keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Returns place_item commands for component_placements/2.

component_placements(state, opts \\ [])

@spec component_placements(map(), keyword() | map()) :: [{String.t(), placement()}]

Returns placements arranged by connected component.

Components are computed with undirected graph membership. Each component uses :strategy (:layered, :tree, or :orthogonal) and is then offset as a separate band.

layered_commands(state, opts \\ [])

@spec layered_commands(map(), keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Returns place_item commands for layered_placements/2.

layered_placements(state, opts \\ [])

@spec layered_placements(map(), keyword() | map()) :: [{String.t(), placement()}]

Returns layered graph placements as {item_id, placement} tuples.

The helper derives layer depth from directed connectors. Items with no incoming connector start at depth zero, and downstream items move one layer at a time. If a graph contains a cycle, the bounded pass count keeps the helper deterministic and returns the deepest placement discovered during the pass window.

Options:

  • :axis - :horizontal (default) or :vertical.
  • :x / :y - origin coordinates. Defaults to the current graph minimum.
  • :layer_gap - distance between depth layers. Default 340.
  • :item_gap - distance between items in the same layer. Default 230.

orthogonal_commands(state, opts \\ [])

@spec orthogonal_commands(map(), keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Returns place_item commands for orthogonal_placements/2.

orthogonal_placements(state, opts \\ [])

@spec orthogonal_placements(map(), keyword() | map()) :: [{String.t(), placement()}]

Returns placements aligned for orthogonal graph routing.

This arrangement keeps directed ranks on one axis and orders items within a rank by current spatial position, giving applications a headless track layout they can pair with orthogonal connector paths.

port_aware_adapter(state, opts \\ [])

@spec port_aware_adapter(map(), keyword() | map()) :: adapter()

Returns a port-aware external layout adapter payload.

The adapter names nodes, ports, connectors, connected components, and graph boundaries using runtime ids. Applications can pass this data to an external layout engine and convert the resulting node coordinates with adapter_commands/3.

tree_commands(state, opts \\ [])

@spec tree_commands(map(), keyword() | map()) :: [
  {:place_item, String.t(), placement()}
]

Returns place_item commands for tree_placements/2.

tree_placements(state, opts \\ [])

@spec tree_placements(map(), keyword() | map()) :: [{String.t(), placement()}]

Returns tree-oriented placements for graph world items.

Roots are items without incoming connectors inside their component. When a cycle or a parentless remainder exists, the remaining items are placed deterministically after the discovered tree ranks.