# `LivePanels.Graph.Query`
[🔗](https://github.com/livepanels/livepanels/blob/v0.1.0/lib/livepanels/graph/query.ex#L1)

Headless graph query helpers for connectors, selections, and navigation.

# `connector_source`

```elixir
@type connector_source() :: LivePanels.Canvas.State.t() | [LivePanels.Item.t()]
```

# `direction`

```elixir
@type direction() :: :incoming | :outgoing | :connected
```

# `navigation_anchor`

```elixir
@type navigation_anchor() ::
  String.t()
  | {:item, String.t()}
  | {:connector, String.t()}
  | LivePanels.Item.t()
  | LivePanels.Canvas.Selection.t()
```

# `adjacency`

```elixir
@spec adjacency(connector_source()) :: %{optional(String.t()) =&gt; [String.t()]}
```

Returns a directed adjacency projection keyed by source item id.

Duplicate target ids are collapsed while preserving first-seen connector order.

# `connector_draft_count`

```elixir
@spec connector_draft_count(map() | term()) :: non_neg_integer()
```

Returns the number of active connector drafts in an assigned draft map.

# `connectors_by_item`

```elixir
@spec connectors_by_item(connector_source()) :: %{
  optional(String.t()) =&gt; [LivePanels.Item.t()]
}
```

Returns a map of item id to all connectors touching that item.

# `connectors_by_port`

```elixir
@spec connectors_by_port(connector_source()) :: %{
  optional({String.t(), String.t() | nil}) =&gt; [LivePanels.Item.t()]
}
```

Returns a map of `{item_id, port_name}` to connectors touching that port.

# `connectors_for_item`

```elixir
@spec connectors_for_item(connector_source(), String.t()) :: [LivePanels.Item.t()]
```

Returns all connectors touching `item_id`.

# `connectors_for_port`

```elixir
@spec connectors_for_port(connector_source(), String.t(), String.t() | atom()) :: [
  LivePanels.Item.t()
]
```

Returns all connectors touching `port_name` on `item_id`.

# `creates_cycle?`

```elixir
@spec creates_cycle?(connector_source(), String.t(), String.t()) :: boolean()
```

Returns true when adding a connector from `from_id` to `to_id` would create a cycle.

# `incoming_connectors`

```elixir
@spec incoming_connectors(connector_source(), String.t()) :: [LivePanels.Item.t()]
```

Returns connectors that target `item_id`.

# `navigation`

```elixir
@spec navigation(connector_source(), navigation_anchor(), direction(), keyword()) ::
  %{
    targets: [String.t()],
    selection: LivePanels.Canvas.Selection.t(),
    command: {:graph_select_elements, map()} | nil
  }
```

Returns ordered item ids reachable from a graph navigation anchor.

# `outgoing_connectors`

```elixir
@spec outgoing_connectors(connector_source(), String.t()) :: [LivePanels.Item.t()]
```

Returns connectors that start from `item_id`.

# `selected_connector?`

```elixir
@spec selected_connector?(LivePanels.Canvas.Selection.t(), String.t()) :: boolean()
```

Returns true when `connector_id` is selected in the given graph selection.

# `selected_item?`

```elixir
@spec selected_item?(LivePanels.Canvas.Selection.t(), String.t()) :: boolean()
```

Returns true when `item_id` is selected in the given graph selection.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
