# `Mob.Socket`
[🔗](https://github.com/genericjam/mob/blob/master/lib/mob/socket.ex#L1)

The socket struct passed through all Mob.Screen and Mob.Component callbacks.

Holds two things:
- `assigns` — the public data map your `render/1` function reads via
  `assigns.foo`, or the `@foo` shorthand inside a `~MOB` template
  (the sigil rewrites `@foo` to `assigns.foo`, matching Phoenix HEEx)
- `__mob__` — internal Mob metadata (screen module, platform, view refs, nav stack)

You interact with a socket via `assign/2` and `assign/3`. Never mutate `__mob__`
directly — it is an internal contract.

# `platform`

```elixir
@type platform() :: :android | :ios
```

# `t`

```elixir
@type t() :: %Mob.Socket{
  __mob__: %{
    :screen =&gt; module() | nil,
    :platform =&gt; platform(),
    :root_view =&gt; term(),
    :view_tree =&gt; map(),
    :nav_stack =&gt; list(),
    :nav_action =&gt; term(),
    optional(:safe_area_confirmed) =&gt; boolean(),
    optional(:last_frame) =&gt; non_neg_integer(),
    optional(:list_renderers) =&gt; map()
  },
  assigns: map()
}
```

# `transition`

```elixir
@type transition() :: :push | :pop | :reset
```

# `assign`

```elixir
@spec assign(t(), keyword() | map()) :: t()
```

Assign multiple key/value pairs at once from a keyword list or map.

    socket = assign(socket, count: 0, name: "test")
    socket = assign(socket, %{count: 0})

# `assign`

```elixir
@spec assign(t(), atom(), term()) :: t()
```

Assign a single key/value pair into the socket's assigns.

    socket = assign(socket, :count, 0)

# `assign_new`

```elixir
@spec assign_new(t(), atom(), (-&gt; term())) :: t()
```

Assign `key` only if it is not already present, computing the value lazily.

    socket = assign_new(socket, :user, fn -> fetch_user(id) end)

`fun` runs only when `key` is absent, so it's the cheap way to set a default
or memoize a lookup across re-renders. Mirrors `Phoenix.LiveView.assign_new/3`.

# `new`

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

Create a new socket for the given screen module.

Options:
- `:platform` — `:android` (default) or `:ios`

# `pop_screen`

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

Pop the current screen, returning to the previous one.

No-op if already at the root of the stack.

# `pop_to`

```elixir
@spec pop_to(t(), atom() | module()) :: t()
```

Pop the stack until the screen registered under `dest` is at the top.

`dest` is a registered atom name or module. No-op if not found in history.

# `pop_to_root`

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

Pop to the root of the current navigation stack.

# `push_screen`

```elixir
@spec push_screen(t(), atom() | module(), map()) :: t()
```

Push a new screen onto the navigation stack.

`dest` is either a registered atom name (e.g. `:counter`) or a screen module
(e.g. `MobDemo.CounterScreen`). `params` are passed to the new screen's
`mount/3` as the first argument.

The push is applied after the current callback returns — `do_render` in
`Mob.Screen` detects the nav_action and mounts the new module.

# `put_root_view`

```elixir
@spec put_root_view(t(), term()) :: t()
```

Store the root view ref returned by the renderer into `__mob__.root_view`.
Called internally after the initial render.

# `reset_to`

```elixir
@spec reset_to(t(), atom() | module(), map(),
  transition: transition(),
  scope: :stack | :all
) :: t()
```

Replace the current navigation stack with a single new screen.

Used for auth transitions (post-login → home with no back button to login).
Pass `transition: :push` or `transition: :pop` when the reset still represents
directional movement, such as switching between custom tabs. The default,
`:reset`, cross-fades. Pass `scope: :all` for an auth boundary that must also
discard every parked tab stack. The default `scope: :stack` preserves the
established current-stack-only behavior.

Raises `ArgumentError` on any other transition — including `:none`, which
would replace the stack while telling the platform no navigation happened,
leaving the incoming screen wearing the outgoing one's view identities.

# `switch_tab`

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

Switch to the named tab in a tab_bar or drawer layout.

By default, switching tabs has no animation. Pass `transition: :push`,
`transition: :pop`, or `transition: :reset` when the tab order implies
directional movement or a cross-fade. `mount_params: %{...}` supplies the
params for the target root's first mount. A previously mounted stack ignores
later mount params and restores its existing screen state.

# `switch_tab`

```elixir
@spec switch_tab(t(), atom(), transition: transition(), mount_params: map()) :: t()
```

# `update`

```elixir
@spec update(t(), atom(), (term() -&gt; term())) :: t()
```

Update an existing assign by applying `fun` to its current value.

    socket = update(socket, :count, fn count -> count + 1 end)

Raises `KeyError` if `key` is not already assigned. Mirrors
`Phoenix.LiveView.update/3`.

---

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