Macaw.Component behaviour (macaw_component v0.1.2)

Copy Markdown View Source

The component contract (spec/01): the behavior every Macaw component implements, and the dispatch functions a host reaches a component through.

defmodule MyApp.Cards do
  use Macaw.Component, name: "my_app.cards", kinds: [:content]

  @impl true
  def declarations(_settings), do: {:ok, reading: :scan}

  @impl true
  def render(:content, _assigns), do: {:safe, ~s(<ul class="cards"></ul>)}
end

Static declarations are use's options (name:, kinds:, hooks:, assets:) and parameters/0; configured declarations are declarations/1's answer, built by Macaw.Component.Declarations.new/2. The dispatch functions answer values: a component's bad answer is an error, never a raise. A component's own raise in render/2 or a transition is its host's process's to take (spec/02 §6).

The contract is unstable until two implementers pass its kit (spec/00 §3).

Summary

Types

A fault: the path to the value, and why.

A kind a component renders as (spec/01 §2).

A contained component's value (spec/02 §7).

Functions

A contained component's bound/3 (spec/02 §7).

A slot's row budget at a size: {:ok, nil} for a component without budget/3, else {:ok, rows} for a positive integer or nil, and {:error, {:bad_budget, answer}} otherwise (spec/01 §1.4).

Whether a module is loaded and uses Macaw.Component.

Whether a module exports every contained transition.

The component's configured declarations for given settings: the settings validated, then declarations/1 called with every bindable parameter at its default (spec/01 §1.1), and its answer built by Macaw.Component.Declarations.new/2.

A contained component's delivery/3 (spec/02 §7).

A fault as a line a person reads.

A component's static declarations, %{name, kinds, hooks, assets}, or :error for a module that is not a component.

A contained component's init/2 (spec/02 §7).

The kinds a component may render as, in order.

The closed observation vocabulary, in order (spec/01 §1.6).

A component's parameters, each checked by Macaw.Data.Parameter.check/1, named by a non-empty string, and, when bindable, with a default (spec/01 §1.1). Every fault at once, its path from the parameter's name.

Given settings checked against the component's parameters, defaults filled in (Macaw.Data.Parameter.validate/2).

A contained component's size/2 (spec/02 §7).

A contained component's four transitions, as {name, arity}.

Types

fault()

@type fault() :: {list(), term()}

A fault: the path to the value, and why.

kind()

@type kind() :: :navigation | :content | :control | :container

A kind a component renders as (spec/01 §2).

value()

@type value() :: term()

A contained component's value (spec/02 §7).

Callbacks

bound(value, name, new)

(optional)
@callback bound(value(), name :: String.t(), new :: term()) :: value()

budget(slot, settings, size)

(optional)
@callback budget(slot :: String.t(), settings :: map(), size :: {number(), number()}) ::
  pos_integer() | nil

declarations(settings)

@callback declarations(settings :: %{required(String.t()) => term()}) ::
  {:ok, keyword() | map()} | {:error, [fault()]}

delivery(value, slot, t)

(optional)
@callback delivery(value(), slot :: String.t(), Macaw.Data.Delivery.t()) :: value()

init(settings, t)

(optional)
@callback init(settings :: map(), Macaw.Component.Context.t()) :: value()

parameters()

@callback parameters() :: %{required(String.t()) => Macaw.Data.Parameter.t()}

render(kind, assigns)

@callback render(kind(), assigns :: map()) :: Phoenix.HTML.Safe.t()

size(value, tuple)

(optional)
@callback size(value(), {number(), number()}) :: value()

Functions

bound(module, value, name, new)

@spec bound(module(), value(), String.t(), term()) :: value()

A contained component's bound/3 (spec/02 §7).

budget(module, slot, settings, size)

@spec budget(module(), String.t(), map(), {number(), number()}) ::
  {:ok, pos_integer() | nil} | {:error, {:bad_budget, term()}}

A slot's row budget at a size: {:ok, nil} for a component without budget/3, else {:ok, rows} for a positive integer or nil, and {:error, {:bad_budget, answer}} otherwise (spec/01 §1.4).

component?(module)

@spec component?(module()) :: boolean()

Whether a module is loaded and uses Macaw.Component.

contained?(module)

@spec contained?(module()) :: boolean()

Whether a module exports every contained transition.

declarations(module, given)

@spec declarations(module(), map()) ::
  {:ok, Macaw.Component.Declarations.t()} | {:error, [fault(), ...]}

The component's configured declarations for given settings: the settings validated, then declarations/1 called with every bindable parameter at its default (spec/01 §1.1), and its answer built by Macaw.Component.Declarations.new/2.

delivery(module, value, slot, delivery)

@spec delivery(module(), value(), String.t(), Macaw.Data.Delivery.t()) :: value()

A contained component's delivery/3 (spec/02 §7).

format_fault(arg)

@spec format_fault(fault()) :: String.t()

A fault as a line a person reads.

info(module)

@spec info(module()) :: {:ok, map()} | :error

A component's static declarations, %{name, kinds, hooks, assets}, or :error for a module that is not a component.

init(module, settings, context)

@spec init(module(), map(), Macaw.Component.Context.t()) :: value()

A contained component's init/2 (spec/02 §7).

kinds()

@spec kinds() :: [kind(), ...]

The kinds a component may render as, in order.

observations()

@spec observations() :: [atom(), ...]

The closed observation vocabulary, in order (spec/01 §1.6).

parameters(module)

@spec parameters(module()) :: {:ok, map()} | {:error, [fault(), ...]}

A component's parameters, each checked by Macaw.Data.Parameter.check/1, named by a non-empty string, and, when bindable, with a default (spec/01 §1.1). Every fault at once, its path from the parameter's name.

settings(module, given)

@spec settings(module(), map()) :: {:ok, map()} | {:error, [fault(), ...]}

Given settings checked against the component's parameters, defaults filled in (Macaw.Data.Parameter.validate/2).

size(module, value, size)

@spec size(module(), value(), {number(), number()}) :: value()

A contained component's size/2 (spec/02 §7).

transitions()

@spec transitions() :: keyword(non_neg_integer())

A contained component's four transitions, as {name, arity}.