# `PhoenixDatastar`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.2.0/lib/phoenix_datastar.ex#L1)

> ### Deprecated {: .warning}
>
> **PhoenixDatastar is deprecated.** Use [Dstar](https://hex.pm/packages/dstar) instead.
> Dstar is a lighter, pure-functions library for Datastar + Plug/Phoenix apps
> without the LiveView-like GenServer abstraction.

PhoenixDatastar view behaviour for building interactive web applications.

## Assigns vs Signals

- **Assigns** (`assign/2,3`, `update/3`) are server-side state, never sent to the
  client. They are available in templates as `@key`. Use them for structs, DB records,
  or any data the server needs to remember.

- **Signals** (`put_signal/2,3`, `update_signal/3`) are Datastar reactive state sent
  to the client via SSE. They must be JSON-serializable. The client accesses them via
  Datastar expressions like `$count`. Signals are **not** available as `@key` in
  templates — Datastar handles their rendering client-side.

Client signals arrive as the `payload` argument to `handle_event/3`. They are untrusted
input — read, validate, and explicitly `put_signal` what you want to send back.

## Usage

For stateless views (no persistent connection):

    defmodule MyApp.CounterStar do
      use PhoenixDatastar

      @impl PhoenixDatastar
      def mount(_params, _session, socket) do
        {:ok, put_signal(socket, :count, 0)}
      end

      @impl PhoenixDatastar
      def handle_event("increment", payload, socket) do
        count = payload["count"] || 0
        {:noreply, put_signal(socket, :count, count + 1)}
      end

      @impl PhoenixDatastar
      def render(assigns) do
        ~H"""
        <div>
          <span data-text="$count"></span>
          <button data-on:click={event("increment")}>+</button>
        </div>
        """
      end
    end

For live views (with persistent SSE connection):

    defmodule MyApp.MultiplayerStar do
      use PhoenixDatastar, :live

      @impl PhoenixDatastar
      def mount(_params, _session, socket) do
        MyApp.PubSub.subscribe("updates")
        {:ok, socket}
      end

      @impl PhoenixDatastar
      def handle_info({:update, data}, socket) do
        {:noreply, patch_elements(socket, "#data", data_fragment(data))}
      end

      @impl PhoenixDatastar
      def terminate(socket) do
        MyApp.cleanup(socket.id)
        :ok
      end
    end

# `handle_event`

```elixir
@callback handle_event(
  event :: String.t(),
  payload :: map(),
  socket :: PhoenixDatastar.Socket.t()
) ::
  {:noreply, PhoenixDatastar.Socket.t()} | {:stop, PhoenixDatastar.Socket.t()}
```

# `handle_info`
*optional* 

```elixir
@callback handle_info(msg :: term(), socket :: PhoenixDatastar.Socket.t()) ::
  {:noreply, PhoenixDatastar.Socket.t()}
```

# `mount`

```elixir
@callback mount(params :: map(), session :: map(), socket :: PhoenixDatastar.Socket.t()) ::
  {:ok, PhoenixDatastar.Socket.t()}
  | {:ok, PhoenixDatastar.Socket.t(), keyword()}
```

# `render`

```elixir
@callback render(assigns :: map()) :: Phoenix.HTML.Safe.t()
```

# `terminate`
*optional* 

```elixir
@callback terminate(socket :: PhoenixDatastar.Socket.t()) :: :ok
```

# `live?`

```elixir
@spec live?(module()) :: boolean()
```

Returns true if the given module is a live PhoenixDatastar view.

A module is considered "live" if it was defined with `use PhoenixDatastar, :live`.
Live views maintain a persistent SSE connection and GenServer state.

## Examples

    iex> PhoenixDatastar.live?(MyApp.StatelessStar)
    false

    iex> PhoenixDatastar.live?(MyApp.LiveStar)
    true

---

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