# `MishkaCmsCore.Runtime.Resources.Validations.StatefulShape`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/resources/__validations/stateful_shape.ex#L5)

Refuses a component that says it keeps state and is shaped so that it cannot.

Two combinations, both of which compiled quietly before this and failed later somewhere the author
could not connect to what they did.

## Declaring a name LiveView owns

`Phoenix.Component.assign/3` and `assign_new/3` refuse five names on a socket: its
`@non_assignables`, `[:uploads, :streams, :socket, :myself]`, and `:flash`, which
`validate_assign_key!/1` refuses in a clause of its own. Neither is exported, so nothing can consult
them; the names are repeated here, which is a copy and is why it is short and named. It is the ONLY
copy: `MishkaCmsCore.UiKit.Contract` and the component compiler read it through
`reserved_names/0`, so the three refusals cannot drift apart.

A function component may declare an attr called `socket` and get away with it because nothing ever
assigns one; a live component cannot, and the failure arrives inside a visitor's LiveView rather
than at the point of writing. A SLOT is the same question: the compiler's `update_many/1` assigns a
declared slot onto the socket under its name exactly as it assigns an attr, so `slot :streams`
raises the moment a parent fills it.

Consequence worth stating: `chelekom-file-field` declares `attr :uploads` and therefore cannot be
stateful — which is correct anyway, since `allow_upload/3` is a `Phoenix.LiveView` function a
LiveComponent cannot call.

## Carrying `extra.clauses`

34 of the kit's installed components dispatch through `extra.clauses`, which compile to a `case`
where each branch has its own root element. A stateful component has to have ONE static root — the
diff raises otherwise — and the compiler's stateful emitter reads the template and not the clause
list, so before this the clauses were silently discarded: a component that rendered only its base
branch, with nothing said anywhere.

Refusing is the honest half of that. The other half is that a single root cannot be proven from a
clause list, only from a render, which is `MishkaCmsCore.Runtime.Compilers.ComponentCompiler`'s
root probe.

## Only what this write changed

A component that was stateless and is being made stateful is checked; one whose `stateful` is not
changing and whose declarations are not changing is left alone, so a row stored before this
validation existed stays editable.

# `reserved_names`

```elixir
@spec reserved_names() :: [String.t()]
```

The names a live component cannot declare, as an attr or as a slot, because LiveView assigns them
itself.

---

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