Plushie.Widget.Build (Plushie v0.7.1)

Copy Markdown View Source

Internal helpers for widget to_node/1 implementations.

Summary

Functions

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

Wraps a widget build pipeline with exit animation handling.

Casts a color value, passing animation descriptors through unchanged.

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

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

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

Resolves a11y derived values from the widget's props.

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

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

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

Validates that a widget has exactly the expected number of 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).