# `OctaStar.Phoenix.Controller`

Phoenix controller helpers for OctaStar.

Use `use OctaStar, :controller` from your web module after
`use Phoenix.Controller` has been applied:

    def controller do
      quote do
        use Phoenix.Controller, formats: [:html]
        use OctaStar, :controller
      end
    end

Controllers implement `OctaStar.StarView`:

    @impl StarView
    def handle_event(conn, "increment", signals), do: ...

## `assign/3` vs `signal/3`

- `assign/3` sets a Plug connection assign. Function components can read it
  via `@key`, but it is never sent to the browser.
- `signal/3` does `assign/3` **and** tracks the key for automatic flushing.
  Function components can read it, and the dispatcher sends it to the Datastar
  client as a signal patch.

# `extract_signals`

```elixir
@spec extract_signals(Plug.Conn.t()) :: [{atom(), term(), keyword()}]
```

Extracts tracked signal keys, values, and per-signal options.

# `flush_signals`

```elixir
@spec flush_signals(Plug.Conn.t()) :: Plug.Conn.t()
```

Flushes tracked signals as Datastar signal patch events.

# `init_signals`

```elixir
@spec init_signals(Plug.Conn.t()) :: String.t() | nil
```

Returns the tracked signal map as JSON for `data-signals`.

# `patch_element`

```elixir
@spec patch_element(Plug.Conn.t(), (map() -&gt; term()) | term(), keyword()) ::
  Plug.Conn.t()
```

Patches a rendered component or HTML value against current assigns.

# `signal`

```elixir
@spec signal(Plug.Conn.t(), atom(), term(), keyword()) :: Plug.Conn.t()
```

Assigns a value and tracks it as a Datastar signal.

---

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