# `MishkaCmsCore.Runtime.PageBuilder.Wizard`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/page_builder/wizard.ex#L5)

Composing a component from its own option lists, before anything is placed.

## What it is for

The examples modal answers "show me one the kit already wrote". This answers the other question —
"give me *this* one" — by turning the component's declared options into a form and the chosen
values into the HEEx an insert places. The two share the modal, the preview pane and the insert
path; only the source of the markup differs.

It exists because an example is a fixed point. A kit ships twelve alerts and none of them is a
small outline alert in the warning colour with an icon, so the author inserts the nearest one and
then edits four properties in the inspector — which is the wizard, done by hand, without the
preview.

## Where the options come from

`Inspector.features/1`, the same fold the property panel uses, keyed by attribute after the
axis→attribute binding (`UiKitHandler.axis_bindings/1`). So the wizard offers exactly the options
the inspector will offer afterwards; a value that can be chosen here can be changed there.

Only attributes with a real option list are offered — a picker over a free-text attribute would be
an empty dropdown. `title`, `class` and friends are the inspector's job once the element is on the
page.

## What it emits

`compose/3` builds the same `<.component component_name=… site=…>` invocation the palette emits, so
the result is an ordinary node: parsed by `Tree.parse/1`, containment-checked, undoable, and
editable afterwards like anything else. Values equal to the component's own default are left out —
writing `variant="default"` says nothing the component does not already say, and every one of them
is another attribute the author has to read past later.

# `axes`

```elixir
@spec axes(map()) :: [
  %{
    name: String.t(),
    label: String.t(),
    values: [String.t()],
    default: String.t() | nil,
    atom?: boolean()
  }
]
```

The axes a wizard can offer: `[%{name:, label:, values:, default:, atom?:}]`.

Ordered the way the panel orders properties, so the wizard and the inspector read the same way
round. An attribute the component declares but has no option list for is skipped. `atom?` rides
along because it changes how the value must be WRITTEN, not how it is chosen.

# `compose`

```elixir
@spec compose(map(), map(), String.t() | nil, :blank | :preview, [map()]) ::
  String.t()
```

The HEEx for a component with these choices.

`choices` is a plain map of attribute name to value, as the form posts it. A value that is blank,
unknown to the attribute, or equal to the component's own default is dropped — the first two
because a wizard must not invent markup the kit cannot render, the third because it is noise.

`components` is the palette, which decides whether a component calling another owns a form.

# `offers?`

```elixir
@spec offers?(map()) :: boolean()
```

Whether a component has anything for the wizard to offer.

A component with no option lists — an icon, a plain wrapper — gets no Wizard tab rather than an
empty one. `chelekom-alert` answers true with five axes; `chelekom-icon` answers false.

---

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