MishkaCmsCore.Runtime.PageBuilder.Wizard (Mishka CMS Core v0.0.1)

Copy Markdown View Source

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.

Summary

Functions

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

The HEEx for a component with these choices.

Whether a component has anything for the wizard to offer.

Functions

axes(entry)

@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(entry, choices, site_name, style \\ :blank, components \\ [])

@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?(entry)

@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.