# `StarView.Controller`
[🔗](https://github.com/Neophen/star_view/blob/v0.7.0/lib/star_view/controller.ex#L1)

Phoenix controller helpers for StarView.

Use `use StarView` from your web module after
`use Phoenix.Controller` has been applied:

    def star_view do
      quote do
        use Phoenix.Controller, formats: [:html, :json]
        use StarView
        use Phoenix.Component

        use Gettext, backend: MyAppWeb.Gettext

        import Phoenix.Component, except: [assign: 3]
        import Plug.Conn

        alias MyAppWeb.Components.StarView.Layout

        plug :put_root_layout, false

        unquote(verified_routes())
      end
    end

Controllers implement `StarView`:

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

`use StarView, checked_events: true` derives event registration from literal
handler names and method patterns. It checks local helpers in `~STAR` and
rejects unknown events or wrong methods before SSE; see `StarView.Events`.

## `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 sends the value to the browser when the
  connection is already an SSE response. Before SSE starts, it records the
  value for `init_signals/1`.

# `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 pre-start signals as Datastar signal patch events.

This is retained for manual flows that call `signal/4` before starting SSE.
Controllers dispatched through `StarView.Dispatch` patch signals immediately
and do not need a final flush.

# `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 exposes it as a Datastar signal.

Before the SSE response starts, the signal is recorded for `init_signals/1`.
During an SSE response, the signal is patched immediately so the browser sees
updates in the same order as the server pipeline.

