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

Copy Markdown View Source

What a component should SAY the moment it is placed.

Dropping chelekom-banner used to put <.component component_name="chelekom-banner" … /> on the canvas — a component with nothing inside it. A banner with no message is a blank strip, an alert with no text is an empty rounded box, and a card with no content is a border. The author drags something, sees almost nothing, and has to open the inspector to discover what they placed.

So a placed component arrives furnished. The text is deliberately ordinary and obviously replaceable — the point is that the shape is visible and the words are already selected for editing, which is what a page builder is for.

Why a table and not the component's own examples

The examples are better copy, but curating them costs a parse of every example the component ships — 7.8 seconds across the palette, to answer a question asked once per drag. The palette builds its drop template for all 177 entries on every render, so this has to be a lookup.

What gets nothing

A component with no inner_block has nowhere to put content, and one that composes its own children — a table row, an accordion — would only be given text in the wrong place. Those stay self-closing, which is what MishkaCmsCore.Builder.PaletteEntry.template/2 emits.

Summary

Functions

The attributes a freshly dropped component arrives SET to, or %{} when it declares none.

The markup to place inside a freshly dropped component, or "" when it takes no content.

Whether a freshly dropped component arrives with something to look at — content between its tags, sample slot entries, or both.

Sample entries for a component's named slots: [{slot_name, attrs, body}].

Whether the component has somewhere to put content at all.

Functions

attrs(entry)

@spec attrs(map()) :: %{optional(String.t()) => String.t()}

The attributes a freshly dropped component arrives SET to, or %{} when it declares none.

A body says what goes inside; this says what the thing itself is. Only a declaration — there is nothing to infer here, and a component that says nothing keeps its own defaults.

body(entry)

@spec body(map()) :: String.t()

The markup to place inside a freshly dropped component, or "" when it takes no content.

Accepts anything shaped like a palette entry — the component's name and its slots are all this reads.

furnished?(entry)

@spec furnished?(map()) :: boolean()

Whether a freshly dropped component arrives with something to look at — content between its tags, sample slot entries, or both.

The predicate the kit-wide contract is written against: chelekom-accordion has nothing to say between its tags and is furnished all the same, by two <:item> entries.

slot_samples(entry)

@spec slot_samples(map()) :: [{String.t(), map(), String.t()}]

Sample entries for a component's named slots: [{slot_name, attrs, body}].

The COPY only — writing it as HEEx belongs to MishkaCmsCore.Builder.PaletteEntry, which already owns how a slot's own required attributes are seeded. attrs carries the values the sample needs to make sense of itself: an <:option> without a value is a choice that cannot be chosen.

Entries are dropped for slots the component does not declare, so a composite's <:header> is only written where there is one to write.

takes_content?(entry)

@spec takes_content?(map()) :: boolean()

Whether the component has somewhere to put content at all.

inner_block is the only slot an author's text can land in. A component without one is not incomplete — a spinner has nothing to say — so it is left alone rather than given a body that Phoenix would refuse.