A2UICore.State.Surface (A2UICore v0.1.1)

Copy Markdown View Source

The state of one UI surface: its identity, catalog selection, theme, data model and components.

A surface is plain data. Mutating operations return the updated surface (and, where something observable happened, effects); nothing is delivered by callback. The processor (A2UICore.Processor) is what applies protocol messages to surfaces.

  • :id — the surface id, unique within a group.
  • :catalog_id — the default catalog's id (nil until resolved).
  • :catalogs — %{catalog_id => catalog} available to the surface.
  • :theme — theme properties (v0.9; empty under v1.0).
  • :send_data_model — whether the renderer should attach this surface's data model to outbound action messages.
  • :root_id — the entry component, "root" by default.
  • :data_model — an A2UICore.State.DataModel.
  • :components — an A2UICore.State.Components.
  • :version — the protocol version the surface was created under.
  • :metadata — free-form host data, never sent on the wire.

Summary

Functions

The surface's default catalog, or nil when it has none.

Builds the action event a component interaction produces, or nil when payload is not an action.

Releases the surface's resources: detaches data-model subscriptions.

Reads from the surface's data model; see A2UICore.State.DataModel.get/2.

Creates a surface. Options: :catalog_id, :catalogs, :theme, :send_data_model, :root_id, :data_model (a model or initial data), :version, :metadata.

The surface's protocol version: its default catalog's, or, for a v1.0 surface without a default catalog, the version it was created under.

Replaces the surface's components.

The catalog an item on the surface runs in: the one catalog_id names (nil names none; an empty string names a catalog too), else the default catalog. subject describes the item in the error, as in "Function call 'formatString'".

Writes into the surface's data model; see A2UICore.State.DataModel.set/3.

Types

t()

(since 0.1.0)
@type t() :: %A2UICore.State.Surface{
  catalog_id: String.t() | nil,
  catalogs: %{optional(String.t()) => term()},
  components: A2UICore.State.Components.t(),
  data_model: A2UICore.State.DataModel.t(),
  id: String.t(),
  metadata: map(),
  root_id: String.t(),
  send_data_model: boolean(),
  theme: map(),
  version: String.t() | nil
}

Functions

default_catalog(surface)

(since 0.1.0)
@spec default_catalog(t()) :: A2UICore.Catalog.t() | nil

The surface's default catalog, or nil when it has none.

dispatch_action(surface, payload, source_component_id, now \\ DateTime.utc_now())

(since 0.1.0)
@spec dispatch_action(t(), term(), String.t(), DateTime.t()) :: map() | nil

Builds the action event a component interaction produces, or nil when payload is not an action.

payload is either an action object (%{"name" => …, "context" => …}) or %{"event" => %{…}}, optionally carrying a "catalogId". The event has name, surfaceId, sourceComponentId, timestamp (RFC 3339, UTC), context (empty when absent or not an object) and, when present, catalogId and userMessage.

now is the event time; it defaults to the current UTC time and is a parameter so callers and tests can keep the core deterministic.

iex> surface = A2UICore.State.Surface.new("main")
iex> now = ~U[2026-01-02 03:04:05Z]
iex> A2UICore.State.Surface.dispatch_action(surface, %{"name" => "save"}, "btn", now)
%{
  "name" => "save",
  "surfaceId" => "main",
  "sourceComponentId" => "btn",
  "timestamp" => "2026-01-02T03:04:05Z",
  "context" => %{}
}

dispose(surface)

(since 0.1.0)
@spec dispose(t()) :: t()

Releases the surface's resources: detaches data-model subscriptions.

get_data(surface, path)

(since 0.1.0)
@spec get_data(t(), term()) :: {:ok, term()} | {:error, A2UICore.Error.t()}

Reads from the surface's data model; see A2UICore.State.DataModel.get/2.

new(id, options \\ [])

(since 0.1.0)
@spec new(String.t(), keyword()) :: t()

Creates a surface. Options: :catalog_id, :catalogs, :theme, :send_data_model, :root_id, :data_model (a model or initial data), :version, :metadata.

iex> surface = A2UICore.State.Surface.new("main", send_data_model: true)
iex> {surface.id, surface.root_id, surface.send_data_model}
{"main", "root", true}

protocol_version(surface)

(since 0.1.0)
@spec protocol_version(t()) :: String.t() | nil

The surface's protocol version: its default catalog's, or, for a v1.0 surface without a default catalog, the version it was created under.

put_components(surface, components)

(since 0.1.0)
@spec put_components(t(), A2UICore.State.Components.t()) :: t()

Replaces the surface's components.

resolve_catalog(surface, catalog_id, subject \\ "Item")

(since 0.1.0)
@spec resolve_catalog(t(), String.t() | nil, String.t()) ::
  {:ok, A2UICore.Catalog.t()} | {:error, A2UICore.Error.t()}

The catalog an item on the surface runs in: the one catalog_id names (nil names none; an empty string names a catalog too), else the default catalog. subject describes the item in the error, as in "Function call 'formatString'".

set_data(surface, path, value)

(since 0.1.0)
@spec set_data(t(), term(), term()) ::
  {:ok, t(), [A2UICore.State.DataModel.notification()]}
  | {:error, A2UICore.Error.t()}

Writes into the surface's data model; see A2UICore.State.DataModel.set/3.