# `Drafter.Widget.Container`
[🔗](https://github.com/jaman/drafter/blob/main/lib/drafter/widget/container.ex#L1)

Holds and arranges child widgets using vertical, horizontal, or stack layouts.

In `:vertical` layout children share height equally; in `:horizontal` they share
width equally. `:stack` overlays all children at the same position, rendering only
the last child's output. Events are forwarded to every child on each dispatch.

Children are widget modules, not element tuples. Each is mounted during
`mount/1` and its state is retained across renders.

## Component tag

This module has no `component_tag/0` and no `Drafter.App` helper. It is used by
placing it in a render tree as a `{module, props}` pair:

    {Drafter.Widget.Container,
     %{
       layout: :vertical,
       children: [
         {Drafter.Widget.Label, %{text: "Top section"}},
         {Drafter.Widget.Label, %{text: "Bottom section"}}
       ]
     }}

The `vertical/2` and `horizontal/2` helpers in `Drafter.App` do not build this
widget — they produce `{:layout, direction, children, opts}` elements that the
component renderer lays out itself.

## Options

  * `:children` - list of `{module, props}` or `{module, props, state}` tuples.
    Default `[]`. A two-element pair is mounted; a three-element one is taken as
    already mounted
  * `:layout` - arrangement: `:vertical` (default), `:horizontal`, `:stack`
  * `:padding` - inner padding in columns and rows. Default `0`
  * `:border_style` - `:none` (default) or any other atom. Any value other than
    `:none` insets the content rect by one cell on every side; no border
    characters are drawn
  * `:style` - `t:map/0` of style properties. Default `%{}`. Carried on the state
    and not consulted while rendering

`update/2` re-reads every option. Supplying `:children` re-mounts each entry given
as a `{module, props}` pair, discarding whatever state that child had accumulated;
pass `{module, props, state}` triples to keep it.

## Widget value

`Drafter.get_widget_value/1` is not implemented for this widget and returns `nil`.

## Usage

    Drafter.Widget.Container.mount(%{
      layout: :horizontal,
      padding: 1,
      children: [
        {Drafter.Widget.Label, %{text: "Left"}},
        {Drafter.Widget.Label, %{text: "Right"}}
      ]
    })

# `child_spec`

```elixir
@type child_spec() ::
  {module(), Drafter.Widget.props()}
  | {module(), Drafter.Widget.props(), Drafter.Widget.state()}
```

# `layout_type`

```elixir
@type layout_type() :: :vertical | :horizontal | :stack
```

# `t`

```elixir
@type t() :: %Drafter.Widget.Container{
  border_style: atom(),
  children: [child_spec()],
  layout: layout_type(),
  padding: non_neg_integer(),
  style: map()
}
```

# `focused`

# `handle_event`

```elixir
@spec handle_event(Drafter.Event.t(), t()) :: {:ok, t()} | {:bubble, t()}
```

Offers the event to every child in order.

Every child sees the event, even after an earlier one handled it. A child
returning `{:ok, _}` or `{:ok, _, _}` marks the event handled; `{:bubble, _}` and
`{:noreply, _}` keep the child's new state without marking it handled, and any
other return leaves that child's state alone. Returns `{:ok, state}` if any child
handled the event and `{:bubble, state}` otherwise; child states are updated
either way. Actions returned by children are discarded.

# `mount`

```elixir
@spec mount(Drafter.Widget.props()) :: t()
```

Builds the container state from `props`, mounting every `{module, props}` child
and leaving `{module, props, state}` triples alone.

    iex> c = Drafter.Widget.Container.mount(%{children: [{Drafter.Widget.Label, %{text: "Hi"}}]})
    iex> [{module, _props, child_state}] = c.children
    iex> {module, child_state.text, c.layout}
    {Drafter.Widget.Label, "Hi", :vertical}

    iex> c = Drafter.Widget.Container.mount(%{})
    iex> {c.children, c.layout, c.padding, c.border_style, c.style}
    {[], :vertical, 0, :none, %{}}

# `new`

```elixir
@spec new(
  [child_spec()],
  keyword()
) :: t()
```

Builds a container struct directly from `children` and `opts`.

Unlike `mount/1` this stores `children` exactly as given, so a `{module, props}`
pair is *not* mounted and `render/2` will fail on it. Use `mount/1` unless the
children are already `{module, props, state}` triples.

Options: `:layout` (default `:vertical`), `:padding` (default `0`),
`:border_style` (default `:none`), `:style` (default `%{}`).

    iex> c = Drafter.Widget.Container.new([], layout: :horizontal, padding: 2)
    iex> {c.children, c.layout, c.padding, c.border_style, c.style}
    {[], :horizontal, 2, :none, %{}}

# `preferred_height`

# `render`

```elixir
@spec render(t(), Drafter.Widget.rect()) :: [Drafter.Draw.Strip.t()]
```

Renders every child into its share of `rect` and stacks the results.

The content rect is inset by `:padding`, plus one further cell on each side when
`:border_style` is not `:none`. `:vertical` gives each child
`div(height, child_count)` rows, `:horizontal` gives each
`div(width, child_count)` columns, and `:stack` gives every child the full rect
but returns only the last child's strips. Returns exactly `rect.height` strips,
each padded to `rect.width`. A child returning `{:error, reason}` contributes no
rows.

# `unmount`

```elixir
@spec unmount(t()) :: :ok
```

Calls `unmount/1` on every child that exports it and returns `:ok`.

# `update`

```elixir
@spec update(Drafter.Widget.props(), t()) :: t()
```

Folds fresh props into `state`.

Re-reads `:layout`, `:padding`, `:border_style` and `:style`. When `:children` is
present the whole child list is rebuilt, mounting each `{module, props}` pair
afresh, so any state those children held is lost.

    iex> c = Drafter.Widget.Container.mount(%{layout: :vertical})
    iex> Drafter.Widget.Container.update(%{layout: :stack, padding: 1}, c).layout
    :stack

# `update_props_from_mount`

---

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