Search documentation of Plushie

# Plushie.Widget.Build (Plushie v0.7.2)

Copy Markdown View Source

Internal helpers for widget `to_node/1` implementations.

## Summary

### Functions

animation_descriptor?(arg1)

Returns true if the value is an animation descriptor (Transition, Spring, or Sequence).

build_node(opts, build_fn)

Wraps a widget build pipeline with exit animation handling.

cast_color_or_passthrough(val)

Casts a color value, passing animation descriptors through unchanged.

children_to_nodes(children)

Converts a list of children (ui_node maps or widget structs) to ui_node() maps.

put_if(props, value, key)

Adds `key => value` to props if value is not nil.

put_if(props, value, key, transform)

Adds `key => transform.(value)` to props if value is not nil.

resolve_a11y(props)

Resolves a11y derived values from the widget's props.

to_node(node)

Converts a child element to a ui_node() map if it's a widget struct.

unknown_option!(module, key)

Raises ArgumentError for an unknown option key passed to a widget constructor.

validate_animation_target!(descriptor, field_type, field_name)

Validates that an animation descriptor's `to` and `from` values are valid for the given field type.

validate_children_count!(id, type, children, expected)

Validates that a widget has exactly the expected number of children.

validate_single_child!(id, type, children)

Validates that a widget has at most one child.

## Functions

# animation_descriptor?(arg1)

    @spec animation_descriptor?(term()) :: boolean()

Returns true if the value is an animation descriptor (Transition, Spring, or Sequence).

# build_node(opts, build_fn)

    @spec build_node(
      opts :: keyword(),
      build_fn :: (keyword() -> Plushie.Widget.ui_node())
    ) ::
      Plushie.Widget.ui_node()

Wraps a widget build pipeline with exit animation handling.

Animation descriptors (Transition, Spring, Sequence) on regular fields go through widget setters which validate the target values. The `exit:` prop is special (not a per-field setter), so it is extracted here and merged onto the node's props after the build function runs.

    Build.build_node(opts, fn widget_opts ->
      Button.new(id, label, widget_opts) |> Button.build()
    end)

# cast_color_or_passthrough(val)

    @spec cast_color_or_passthrough(term()) :: term()

Casts a color value, passing animation descriptors through unchanged.

Used by generated `to_node/1` code for Color-typed fields where struct defaults bypass setters. Animation descriptors need to reach Tree.normalize intact for encoding via `encode_value/1`.

# children_to_nodes(children)

    @spec children_to_nodes(children :: [Plushie.Widget.child()]) :: [
      Plushie.Widget.ui_node()
    ]

Converts a list of children (ui_node maps or widget structs) to ui_node() maps.

# put_if(props, value, key)

    @spec put_if(props :: map(), value :: term(), key :: atom()) :: map()

Adds `key => value` to props if value is not nil.

# put_if(props, value, key, transform)

    @spec put_if(
      props :: map(),
      value :: term(),
      key :: atom(),
      transform :: (term() -> term())
    ) :: map()

Adds `key => transform.(value)` to props if value is not nil.

# resolve_a11y(props)

    @spec resolve_a11y(props :: map()) :: map()

Resolves a11y derived values from the widget's props.

If the a11y prop has a `label_from` directive, the referenced prop's value is used as the accessible label. Called during to_node after all props are set.

# to_node(node)

    @spec to_node(child :: Plushie.Widget.child()) :: Plushie.Widget.ui_node()

Converts a child element to a ui_node() map if it's a widget struct.

# unknown_option!(module, key)

    @spec unknown_option!(module :: module(), key :: term()) :: no_return()

Raises ArgumentError for an unknown option key passed to a widget constructor.

# validate_animation_target!(descriptor, field_type, field_name)

    @spec validate_animation_target!(
      descriptor :: term(),
      field_type :: term(),
      field_name :: atom()
    ) :: :ok

Validates that an animation descriptor's `to` and `from` values are valid for the given field type.

Called by generated animation setter clauses. Raises `ArgumentError` if validation fails. Skips validation for `:any` typed fields.

# validate_children_count!(id, type, children, expected)

    @spec validate_children_count!(
      id :: String.t(),
      type :: String.t(),
      children :: [Plushie.Widget.child()],
      expected :: pos_integer()
    ) :: :ok

Validates that a widget has exactly the expected number of children.

Raises `ArgumentError` if the children count does not match `expected`. The error message includes the widget type, ID, and both the expected and actual counts:

    ** (ArgumentError) overlay "popup" requires exactly 2 children, got 1

Called at the top of `to_node/1` for widgets with strict child count requirements (overlay).

# validate_single_child!(id, type, children)

    @spec validate_single_child!(
      id :: String.t(),
      type :: String.t(),
      children :: [Plushie.Widget.child()]
    ) :: :ok

Validates that a widget has at most one child.

Raises `ArgumentError` if the children list has more than one element. The error message includes the widget type and ID for easy diagnosis:

    ** (ArgumentError) container "sidebar" accepts at most 1 child, got 3

Called at the top of `to_node/1` for single-child wrappers (container, tooltip, pointer_area, scrollable, themer, floating, responsive, pin, sensor, window).