# `A2UIAgent.Macro`
[🔗](https://github.com/a2ui-elixir/a2ui/blob/v0.1.1/umbrella/apps/a2ui_agent/lib/a2ui_agent/macro.ex#L1)

A macro: a component the model can write that the agent expands into
components of its catalog before they reach the renderer.

    import A2UIAgent.Builder.Basic

    status_badge =
      A2UIAgent.Macro.new(
        "StatusBadge",
        [status: :string, title: :string],
        fn %{status: status, title: title} ->
          card(
            child:
              row(
                children: [
                  text(text: String.upcase(status), variant: "caption"),
                  text(text: title, variant: "h3")
                ]
              )
          )
        end,
        description: "A status badge."
      )

The model writes `{"id": "badge", "component": "StatusBadge",
"status": "active", "title": "Server 1"}`; `A2UIAgent.MacroExpander`
replaces it with the flattened tree, rooted at `badge`. The macro's
catalog schema (`to_json_schema/2`) is derived from its parameters.

## Parameters

Parameters are a keyword list of names and types, in order. A type can
also be given with options, `title: [type: :string, description:
"..."]`: `:description` (default: the name, spaced and capitalized),
`:required` (default `true` unless a `:default` is given) and
`:default`, passed for an optional parameter left out. Types:

  * `:string`, `:integer`, `:number`, `:boolean`, `:object`, `:any`,
    `{:enum, values}` and `{:list, type}`;
  * `:component`, a child slot: the model passes a component id, which
    reaches the function as an `A2UIAgent.Builder.ref/1`;
  * `:component_list`, child slots: a list of ids, as refs;
  * `:action`: an event name, an event (`{"name": ..., "context": ...}`)
    or an action, as an action;
  * `:dynamic_string`, `:dynamic_number`, `:dynamic_boolean`,
    `:dynamic_string_list`, `:dynamic_value`, `:data_binding`,
    `:function_call`, `:check_rule` and `:accessibility`: the
    protocol's common types.

Any argument written as a binding (`{"path": ...}`) reaches the
function as an `A2UIAgent.Builder.bind/1`.

The function gets a map of the arguments by parameter name and returns
a component tree. It may call other macros with `call/2`.

# `parameter`
*since 0.1.0* 

```elixir
@type parameter() :: %{
  name: atom(),
  type: type(),
  required: boolean(),
  default: term(),
  description: String.t()
}
```

# `t`
*since 0.1.0* 

```elixir
@type t() :: %A2UIAgent.Macro{
  description: String.t() | nil,
  fun: (map() -&gt; A2UIAgent.Builder.tree()),
  name: String.t(),
  parameters: [parameter()]
}
```

# `type`
*since 0.1.0* 

```elixir
@type type() ::
  :string
  | :integer
  | :number
  | :boolean
  | :object
  | :any
  | {:enum, [term()]}
  | {:list, type()}
  | :component
  | :component_list
  | :action
  | :dynamic_string
  | :dynamic_number
  | :dynamic_boolean
  | :dynamic_string_list
  | :dynamic_value
  | :data_binding
  | :function_call
  | :check_rule
  | :accessibility
```

# `build`
*since 0.1.0* 

```elixir
@spec build(t(), keyword() | map()) :: A2UIAgent.Builder.tree()
```

Runs the macro with `args` (by parameter name, as atoms or strings)
and returns its tree. Arguments are coerced as the parameters' types
say (see "Parameters"); a left-out optional parameter gets its
default.

Raises `ArgumentError` for an unknown or missing argument, or when the
function does not return a component tree.

# `call`
*since 0.1.0* 

```elixir
@spec call(t() | String.t(), keyword() | map()) :: A2UIAgent.Macro.Call.t()
```

A call of `macro` (a macro, or the name of one the flattening is given
with `:macros`) inside a tree. The call expands where the tree is
flattened, in the tree's scope: the components it makes are named
after the tree's root.

# `new`
*since 0.1.0* 

```elixir
@spec new(String.t(), keyword(), (map() -&gt; A2UIAgent.Builder.tree()), keyword()) ::
  t()
```

Defines a macro named `name` (the component name the model writes).
Option: `:description`, the component's description in the catalog.

Raises `ArgumentError` for a parameter with an unknown type.

# `to_json_schema`
*since 0.1.0* 

```elixir
@spec to_json_schema(t(), String.t()) :: map()
```

The macro's component schema for a catalog: an object whose properties
are the parameters, with references to the protocol's common types
under `ref_prefix`.

    iex> macro = A2UIAgent.Macro.new("Badge", [label: :dynamic_string], fn _ -> nil end)
    iex> A2UIAgent.Macro.to_json_schema(macro)
    %{
      "type" => "object",
      "properties" => %{
        "label" => %{"$ref" => "common_types.json#/$defs/DynamicString", "description" => "Label"}
      },
      "required" => ["label"]
    }

---

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