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

Renders a single line or multi-line string of styled text.

Supports semantic variants that apply theme colors automatically, and accepts
an explicit style map for full control over foreground and background colors.

## Component tag

Tag `:label`, built by `Drafter.App` as `{:label, text, opts}`:

    label(text, opts)

The positional argument becomes `:text`. All other props come from `opts`.

## Options

  * `:text` - `t:String.t/0` to render. Default `""`. Supplied positionally
    through the `label/2` element. A `"\n"` splits it into one strip per line.
    A list of `{text, style}` runs instead draws one line of those pieces side by
    side, each in its own style over the label's; the widget's `:text` is then the
    runs' text joined
  * `:style` - `t:map/0` of style properties, e.g. `%{fg: {255, 100, 0},
    bold: true}`. Default `%{}`
  * `:align` - text alignment: `:left` (default), `:center`, `:right`
  * `:variant` - semantic colour: `:default` (default), `:primary`, `:success`,
    `:warning`, `:error`, `:muted`. Anything other than `:default` is also added
    as a theme class while rendering
  * `:class` - theme class atom or list of them, reaching `mount/1` as
    `:classes`. Default `[]`
  * `:app_module` - module supplying a per-app theme, passed by the renderer as
    `:__app_module__`. Default `nil`

`update/2` accepts `:text`, `:style`, `:align`, `:variant`, `:classes` and
`:app_module`, and silently drops any other key. All of them are live-updatable
through the component tree.

## Widget value

`Drafter.get_widget_value/1` returns the label's `:text` as a `t:String.t/0`,
because the value extractor reads the `:text` field.

## Usage

    label("Hello world", style: %{fg: {100, 200, 255}, bold: true})
    label("Warning!", variant: :warning)
    label("Centered", align: :center)

# `align`

```elixir
@type align() :: :left | :center | :right
```

# `t`

```elixir
@type t() :: %Drafter.Widget.Label{
  align: align(),
  app_module: module() | nil,
  classes: [atom()],
  runs: term(),
  style: map(),
  text: String.t(),
  variant: variant()
}
```

# `variant`

```elixir
@type variant() :: :default | :primary | :success | :warning | :error | :muted
```

# `component_tag`

```elixir
@spec component_tag() :: :label
```

The registry tag for this widget.

    iex> Drafter.Widget.Label.component_tag()
    :label

# `focused`

# `from_component_opts`

```elixir
@spec from_component_opts(
  term(),
  keyword()
) :: Drafter.Widget.props()
```

Turns the `{:label, text, opts}` element into a props map for `mount/1`.

`text` is the positional argument. `:class` is normalised into `:classes` and
`:__app_module__` becomes `:app_module`.

    iex> Drafter.Widget.Label.from_component_opts("Hi", align: :right)
    %{text: "Hi", style: %{}, align: :right, variant: :default, classes: [], app_module: nil}

# `handle_event`

# `mount`

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

Builds the label state from `props`.

    iex> l = Drafter.Widget.Label.mount(%{text: "Hi", variant: :warning})
    iex> {l.text, l.variant, l.align}
    {"Hi", :warning, :left}

    iex> l = Drafter.Widget.Label.mount(%{})
    iex> {l.text, l.style, l.align, l.variant, l.classes, l.app_module}
    {"", %{}, :left, :default, [], nil}

# `new`

```elixir
@spec new(
  String.t(),
  keyword()
) :: t()
```

Builds a label struct directly from `text` and `opts`.

Reads `:style` (default `%{}`), `:align` (default `:left`) and `:variant`
(default `:default`). `:classes` and `:app_module` are not read here and stay at
their struct defaults; use `mount/1` to set them.

    iex> l = Drafter.Widget.Label.new("Hello", align: :center)
    iex> {l.text, l.align, l.variant, l.classes}
    {"Hello", :center, :default, []}

# `preferred_height`

```elixir
@spec preferred_height(
  term(),
  keyword()
) :: pos_integer()
```

Always `1`, whatever the text contains — a multi-line label still reserves a
single row.

# `render`

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

Draws the text into `rect`, one strip per newline-separated line.

Empty text yields a single blank strip. Each line is padded to `rect.width`
according to `:align`, or cropped to it when it is longer. `rect.height` is not
consulted, so a label with more lines than rows overflows.

# `unmount`

# `update`

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

Folds fresh props into `state`.

Only `:text`, `:style`, `:align`, `:variant`, `:classes` and `:app_module` are
applied; any other key in `props` is dropped without error.

    iex> l = Drafter.Widget.Label.mount(%{text: "Hi"})
    iex> updated = Drafter.Widget.Label.update(%{text: "Bye", nonsense: 1}, l)
    iex> {updated.text, updated.align}
    {"Bye", :left}

# `update_props_from_mount`

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

Returns `mount_props` unchanged, so a re-render passes every option through to
`update/2`.

---

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