Behaviour every Athanor-aware component implements.
At v1 only metadata/0 is required. Every other callback has a default
injected by use Athanor.Component that components can override at will.
Defining a component
defmodule MyApp.Components.Promo do
use Athanor.Component
@impl Athanor.Component
def metadata, do: %{type: "promo", label: "Promo", icon: "fa-bullhorn"}
@impl Athanor.Component
def required_props, do: ["headline"]
@impl Athanor.Component
def render(:live, node, _ctx) do
assigns = %{headline: node["props"]["headline"]}
~H"<h2>{@headline}</h2>"
end
endRender targets
Only :live is supported in v1. Future steps add :static, :mjml, :text
without breaking the callback signature.
Editor configuration: two ways
Components describe how they are edited in one of two ways.
Preferred: fields/0 (declarative)
Return a list of field tuples describing inputs. Athanor auto-generates the configure panel.
def fields, do: [
{"title", :text, label: "Title"},
{"level", :select, label: "Level", options: [{"H1", "1"}, {"H2", "2"}]},
{"image", :custom, label: "Image", module: MyApp.MediaPicker}
]Built-in types: :text, :textarea, :number, :select, :color,
:checkbox. The :custom type mounts a consumer-supplied module
implementing Athanor.Field. See Athanor.Field and Athanor.Fields.
Legacy: editor_form/0 (LiveComponent)
Return a Phoenix.LiveComponent module the editor mounts directly.
Use this when you need state, multi-step flows, or behaviour the
built-in field types don't cover. Return nil (default) for no
configuration.
Dispatch order
When both are defined, fields/0 (returning a non-empty list) wins.
See Athanor.Renderer for the full dispatch rules.
Child zones
Container components (e.g., Columns) override child_zones/1 to expose
their children to Athanor.Tree walk/find/insert/remove/move. Default
is no children.
Summary
Functions
Default validate/1 used when a component does not override.