# `Alaja.Wizard`
[🔗](https://github.com/Lorenzo-SF/alaja/blob/2.1.0/lib/alaja/wizard.ex#L1)

Declarative multi-field form renderer for Alaja.

A Wizard holds an ordered list of fields (name, label, type, value,
default, hint). It does NOT run interactively — it renders to an
`Alaja.Buffer.t/0` via one of the five neutral renderers:

    :inline           — all fields on one line, comma-separated
    :compact          — two-column table (label | value)
    :stacked          — one field per row, label above value
    :wizard           — boxed form with progress marker
    :compact_wizard   — boxed form, single-line per field

Renderers are pure: same input, same output Buffer. Use
`Alaja.Printer.print_raw/2` (or your own Buffer consumer) to flush.

## Example

    w =
      Alaja.Wizard.new()
      |> Alaja.Wizard.field(:name, :string, label: "Name", default: "alice")
      |> Alaja.Wizard.field(:age, :integer, label: "Age", default: 30)
      |> Alaja.Wizard.field(:newsletter, :boolean, label: "Subscribe?", default: true)

    Alaja.Wizard.render(w, :compact) |> Alaja.Printer.print_raw()

See `render/2` for the full dispatcher and `field/3` for accepted
options.

# `field`

```elixir
@type field() :: %{
  name: atom(),
  label: String.t(),
  type: field_type(),
  value: any(),
  default: any(),
  hint: String.t() | nil,
  values: [any()] | nil
}
```

# `field_type`

```elixir
@type field_type() :: :string | :integer | :float | :boolean | :enum | :path | :url
```

# `t`

```elixir
@type t() :: %Alaja.Wizard{
  fields: [field()],
  renderer: :inline | :compact | :stacked | :wizard | :compact_wizard,
  title: String.t() | nil
}
```

# `field`

```elixir
@spec field(t(), atom(), field_type(), keyword()) :: t()
```

Appends a field to the wizard.

## Options

  - `:label`     — human-readable label (defaults to `Atom.to_string(name)`)
  - `:default`   — default value applied when `value` is unset
  - `:hint`      — small helper text shown beneath the field
  - `:values`    — for `:enum` type, the allowed atoms/strings

The current value falls back to `:default` if `:value` is not given.
Use `set/3` to mutate a value in-place on a wizard.

# `new`

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

Starts a new empty Wizard.

## Options

  - `:title` — title rendered at the top of boxed renderers
  - `:renderer` — default renderer for `render/1` (default `:compact`)

# `render`

```elixir
@spec render(t(), :inline | :compact | :stacked | :wizard | :compact_wizard | nil) ::
  Alaja.Buffer.t()
```

Renders the wizard to an `Alaja.Buffer.t/0` using the named renderer.

Recognised renderers: `:inline, :compact, :stacked, :wizard,
:compact_wizard`. Any other atom raises `ArgumentError`.

# `set`

```elixir
@spec set(t(), atom(), any()) :: t()
```

Sets the value of an existing field by name.

Raises `ArgumentError` if no field with that name exists.

---

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