# `Choreo.Sequence`
[🔗](https://github.com/code-shoily/choreo/blob/v0.14.1/lib/choreo/sequence.ex#L1)

Sequence diagrams for Choreo.

Sequence diagrams show how participants interact with each other over time.
Unlike most other Choreo modules, this module is heavily skewed toward
Mermaid's native `sequenceDiagram` syntax — GraphViz has no native
sequence-diagram concept, so the DOT renderer is provided as a best-effort
timeline-style fallback.

## Supported features

- **Participants** and **Actors** (external roles)
- **Synchronous**, **asynchronous**, **return**, and **self** messages
- **Activation boxes** (`activate` / `deactivate`)
- **Notes** (`over`, `left`, `right` of a participant, or `between` two)
- **Loops** and fragments (`loop`, `opt`, `alt`/`else`, `par`, `break`, `critical`)

## Example

    iex> alias Choreo.Sequence
    iex> Sequence.new()
    ...> |> Sequence.add_actor(:user, label: "User")
    ...> |> Sequence.add_participant(:api, label: "API")
    ...> |> Sequence.add_participant(:db, label: "Database")
    ...> |> Sequence.message(:user, :api, label: "GET /accounts")
    ...> |> Sequence.activate(:api)
    ...> |> Sequence.message(:api, :db, label: "SELECT * FROM accounts")
    ...> |> Sequence.return(:db, :api, label: "rows")
    ...> |> Sequence.deactivate(:api)
    ...> |> Sequence.return(:api, :user, label: "200 OK")
    ...> |> Sequence.to_mermaid()
    ...> |> String.split("\n")
    ...> |> Enum.take(4)
    ["sequenceDiagram", "    actor user as User", "    participant api as API", "    participant db as Database"]

# `event_type`

```elixir
@type event_type() :: :message | :activation | :note | :fragment
```

# `fragment_kind`

```elixir
@type fragment_kind() ::
  :loop | :opt | :alt | :else | :and | :par | :break | :critical
```

# `message_type`

```elixir
@type message_type() :: :sync | :async | :return | :self
```

# `note_position`

```elixir
@type note_position() ::
  {:over, atom()}
  | {:left, atom()}
  | {:right, atom()}
  | {:between, atom(), atom()}
```

# `t`

```elixir
@type t() :: %Choreo.Sequence{
  edge_meta: term(),
  events: term(),
  graph: term(),
  next_order: term(),
  participants: term()
}
```

# `activate`

```elixir
@spec activate(t(), atom()) :: t()
```

Emits an `activate` event for the given participant.

# `add_actor`

```elixir
@spec add_actor(t(), atom(), keyword()) :: t()
```

Adds an actor (external person or system) to the diagram.

## Options

- `:label` - display name (defaults to `Macro.camelize/1` of the id)
- `:description` - longer description (used by analysis, not rendered)

# `add_participant`

```elixir
@spec add_participant(t(), atom(), keyword()) :: t()
```

Adds a participant to the diagram.

## Options

- `:label` - display name
- `:description` - longer description

# `async`

```elixir
@spec async(t(), atom(), atom(), keyword()) :: t()
```

Adds an asynchronous message.

# `deactivate`

```elixir
@spec deactivate(t(), atom()) :: t()
```

Emits a `deactivate` event for the given participant.

# `end_fragment`

```elixir
@spec end_fragment(t()) :: t()
```

Ends the most recently started fragment.

# `events`

```elixir
@spec events(t()) :: [map()]
```

Returns all ordered events in the diagram.

# `fragment`

```elixir
@spec fragment(t(), fragment_kind(), String.t() | nil) :: t()
```

Starts a fragment (loop, opt, alt, par, break, critical).

## Examples

    seq
    |> Sequence.fragment(:loop, "for each item")
    |> Sequence.message(:a, :b, label: "process")
    |> Sequence.end_fragment()

    seq
    |> Sequence.fragment(:alt, "x > 0")
    |> Sequence.message(:a, :b, label: "positive")
    |> Sequence.fragment(:else, "otherwise")
    |> Sequence.message(:a, :b, label: "negative")
    |> Sequence.end_fragment()

# `message`

```elixir
@spec message(t(), atom(), atom(), keyword()) :: t()
```

Adds a message from `from` to `to`.

## Options

- `:label` - message label
- `:type` - `:sync` (default), `:async`, `:return`, or `:self`

A self-message is automatically detected when `from == to`.

# `messages`

```elixir
@spec messages(t()) :: [map()]
```

Returns messages in chronological order.

# `new`

```elixir
@spec new(keyword()) :: t()
```

Creates a new empty sequence diagram.

# `note`

```elixir
@spec note(t(), note_position(), String.t()) :: t()
```

Adds a note to the diagram.

`position` can be:

- `{:over, :alice}`
- `{:left, :alice}`
- `{:right, :alice}`
- `{:between, :alice, :bob}`

# `participant`

```elixir
@spec participant(t(), atom()) :: map() | nil
```

Returns metadata for a participant.

# `participant_labels`

```elixir
@spec participant_labels(t()) :: %{required(atom()) =&gt; String.t()}
```

Returns a map of participant IDs to display labels.

# `participants`

```elixir
@spec participants(t()) :: [atom()]
```

Returns all participants/actors in the diagram.

# `return`

```elixir
@spec return(t(), atom(), atom(), keyword()) :: t()
```

Adds a return message.

# `self_message`

```elixir
@spec self_message(t(), atom(), keyword()) :: t()
```

Adds a self-message on the given participant.

# `theme`

```elixir
@spec theme(atom(), keyword()) :: Choreo.Theme.t()
```

Returns a theme for `Choreo.Sequence`.

## Examples

    iex> theme = Choreo.Sequence.theme(:default, graph_rankdir: :lr)
    iex> theme.graph_rankdir
    :lr

# `to_dot`

```elixir
@spec to_dot(t(), keyword()) :: String.t()
```

Renders the diagram as a DOT graph (best-effort timeline view).

# `to_mermaid`

```elixir
@spec to_mermaid(t(), keyword()) :: String.t()
```

Renders the diagram as a Mermaid sequence diagram.

---

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