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

Renders a single-row application header bar with a centred title and optional live clock.

With `:show_clock` set, a recurring 1-second timer is started during `mount/1`
and the current local time is rendered at the right edge. The title is centred
in the remaining space. Clock format can be either `:time` (`HH:MM:SS`, default)
or `:datetime` (`YYYY-MM-DD HH:MM:SS`). The clock is off unless asked for, so a
header starts no timer of its own.

## Component tag

Tag `:header`, built by `Drafter.App` as `{:header, title, opts}`:

    header(title, opts)

The positional argument becomes `:title`, falling back to `opts[:title]` when
`nil`. `:app_module` is supplied by the renderer.

## Options

  * `:title` - `t:String.t/0` displayed in the centre of the header. Default `""`.
    Supplied positionally through the `header/2` element, falling back to
    `opts[:title]` when the positional value is `nil`
  * `:show_clock` - `t:boolean/0`. Default `false`. When true, `mount/1` schedules a
    `:clock_tick` message one second out, which `handle_event/2` reschedules on
    every tick. No timer is started when no app is registered
  * `:clock_format` - `:time` (default, `HH:MM:SS`) or `:datetime`
    (`YYYY-MM-DD HH:MM:SS`). Any other value falls back to `:time`
  * `:app_module` - module used for theme resolution, passed by the renderer as
    `:__app_module__`. Default `nil`

`update/2` re-reads all four options and starts or cancels the clock timer as
`:show_clock` changes. Through the component tree, however, only `:title` and
`:app_module` are re-applied on a re-render, making `:show_clock` and
`:clock_format` effectively mount-only there.

## Widget value

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

## Usage

    header(title: "My App")
    header(title: "Dashboard", show_clock: true, clock_format: :datetime)

# `t`

```elixir
@type t() :: %Drafter.Widget.Header{
  app_module: module() | nil,
  clock_format: :time | :datetime,
  show_clock: boolean(),
  timer_ref: reference() | nil,
  title: String.t()
}
```

# `component_tag`

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

The registry tag for this widget.

    iex> Drafter.Widget.Header.component_tag()
    :header

# `from_component_opts`

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

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

A `nil` positional `title` falls back to `opts[:title]` and then to `""`.
`:__app_module__` becomes `:app_module`.

    iex> Drafter.Widget.Header.from_component_opts(nil, title: "Dashboard")
    %{title: "Dashboard", show_clock: false, clock_format: :time, app_module: nil}

# `handle_event`

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

Reschedules the clock on `:clock_tick`, returning `{:ok, state}` with the new
timer reference, or with `nil` when `:show_clock` is off. Every other event
returns `{:noreply, state}`.

    iex> h = Drafter.Widget.Header.mount(%{show_clock: false})
    iex> Drafter.Widget.Header.handle_event(:anything_else, h) |> elem(0)
    :noreply

# `mount`

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

Builds the header state from `props` and starts the clock timer when
`:show_clock` is true and an app is registered.

    iex> h = Drafter.Widget.Header.mount(%{title: "My App", show_clock: false})
    iex> {h.title, h.show_clock, h.clock_format, h.timer_ref}
    {"My App", false, :time, nil}

# `preferred_height`

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

Always `1`: the header occupies a single row.

# `render`

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

Draws the header bar into `rect`, returning exactly `rect.height` strips of which
only the first carries content.

The clock sits at the right edge and the title is centred in the columns left over
after one space of margin on each side. A title longer than that space is cut.

# `update`

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

Folds fresh props into `state`, re-reading `:title`, `:show_clock`,
`:clock_format` and `:app_module`.

Turning `:show_clock` on with no timer running starts one; turning it off cancels
the running timer.

    iex> h = Drafter.Widget.Header.mount(%{title: "One", show_clock: false})
    iex> Drafter.Widget.Header.update(%{title: "Two"}, h).title
    "Two"

# `update_props_from_mount`

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

Narrows the props a re-render feeds to `update/2` to `:title` and `:app_module`,
so a re-render never restarts or stops the clock.

---

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