A2UI.ComponentTree (A2UI v0.3.0)

Copy Markdown View Source

Operations on the A2UI component adjacency list.

Components are stored as a flat %{id => %Component{}} map. This module provides functions to walk the tree via ID references without reconstructing a nested structure.

Summary

Functions

Determines how a component references its children.

Expands a template configuration into virtual component instances.

Finds the root component (id "root") in the components map.

Validates that all child ID references in components point to existing components.

Functions

child_ids(component)

@spec child_ids(A2UI.Component.t()) ::
  {:ids, [String.t()]} | {:template, map()} | {:none, []}

Determines how a component references its children.

Returns:

  • {:ids, [id]} — for "child" (single) or "children" (list) props
  • {:template, template_config} — for "children" map with "template" key
  • {:none, []} — when no children are referenced

Examples

iex> comp = %A2UI.Component{id: "c", type: "Card", props: %{"child" => "inner"}}
iex> A2UI.ComponentTree.child_ids(comp)
{:ids, ["inner"]}

iex> comp = %A2UI.Component{id: "r", type: "Row", props: %{"children" => ["a", "b"]}}
iex> A2UI.ComponentTree.child_ids(comp)
{:ids, ["a", "b"]}

expand_template(template_config, data_model, base_path \\ "")

@spec expand_template(map(), A2UI.DataModel.t(), String.t()) ::
  {:ok, [{String.t(), non_neg_integer(), String.t()}]} | {:error, atom()}

Expands a template configuration into virtual component instances.

Given a template config like %{"componentId" => "item", "path" => "/items"}, looks up the array at path in the data model and produces one entry per element.

Returns {:ok, [{virtual_id, index, scope_path}]} or {:error, reason}.

Virtual IDs follow the pattern "componentId__index". Scope paths follow "base_path/path/index".

root(components)

@spec root(%{required(String.t()) => A2UI.Component.t()}) ::
  {:ok, A2UI.Component.t()} | {:error, :no_root}

Finds the root component (id "root") in the components map.

Examples

iex> components = %{"root" => %A2UI.Component{id: "root", type: "Column"}}
iex> A2UI.ComponentTree.root(components)
{:ok, %A2UI.Component{id: "root", type: "Column"}}

validate_references(components)

@spec validate_references(%{required(String.t()) => A2UI.Component.t()}) ::
  :ok | {:error, {:missing_refs, [{String.t(), String.t()}]}}

Validates that all child ID references in components point to existing components.

Returns :ok if all references are valid, or {:error, {:missing_refs, list}} with a list of {parent_id, missing_child_id} tuples.