defmodule FlintUI.API.Attribute do @moduledoc """ Phoenix LiveView attribute helpers. """ alias FlintUI.Theme @doc """ Defines a class attribute for the component trying to fetch the default value from the theme if no default value is provided. """ defmacro color(opts \\ []) do name = Keyword.get(opts, :name) |> component_name(__CALLER__) default = Keyword.get(opts, :default, Theme.get_in_theme(name, [:default, :color]) || :dark) doc = Keyword.get(opts, :doc, "The color of the #{humanize_name(name)}.") quote do attr(:color, :atom, default: unquote(default), doc: unquote(doc) ) end end @doc """ Defines a size attribute for the component trying to fetch the default value and values list from the theme if no values are provided for those. """ defmacro size(opts \\ []) do name = Keyword.get(opts, :name) |> component_name(__CALLER__) values = Keyword.get(opts, :values, Theme.size_variants()) default = Keyword.get(opts, :default, Theme.get_in_theme(name, [:default, :size]) || :md) doc = Keyword.get(opts, :doc, "The size of the #{humanize_name(name)}.") quote do attr(:size, :atom, values: unquote(values), default: unquote(default), doc: unquote(doc) ) end end @doc """ Defines a radius attribute for the component trying to fetch the default value and values list from the theme if no values are provided for those. """ defmacro radius(opts \\ []) do name = Keyword.get(opts, :name) |> component_name(__CALLER__) values = Keyword.get(opts, :values, Theme.radius_variants()) default = Keyword.get(opts, :default, Theme.get_in_theme(name, [:default, :radius]) || :full) doc = Keyword.get(opts, :doc, "The radius of the #{humanize_name(name)}.") quote do attr(:radius, :atom, values: unquote(values), default: unquote(default), doc: unquote(doc) ) end end defp component_name(nil, caller) do FlintUI.Component.module_to_component_name(caller.module) end defp component_name(name, _caller) when is_binary(name) do FlintUI.Component.string_to_component_name(name) end defp component_name(name, _caller) when is_atom(name), do: name defp humanize_name(name) when is_atom(name) do FlintUI.Component.humanize_component_name(name) end @doc """ Tries to convert an user input value value to an integer value and returns a default value if the conversion fails. """ def as_integer(value, default \\ nil) def as_integer(value, _default) when is_integer(value), do: value def as_integer(value, _default) when is_float(value), do: trunc(value) def as_integer(value, default) when is_binary(value) do try do String.to_integer(value) rescue ArgumentError -> default end end def as_integer(_value, default), do: default @doc """ Tries to convert an user input value to a boolean value and returns a default value if the conversion fails. """ def as_boolean(value, default \\ false) def as_boolean(value, _default) when is_boolean(value), do: value def as_boolean("true", _default), do: true def as_boolean("1", _default), do: true def as_boolean("false", _default), do: false def as_boolean("0", _default), do: false def as_boolean(value, default) when is_binary(value) do case Integer.parse(value) do {int, _rest} -> as_boolean(int, default) _ -> default end end def as_boolean(value, _default) when is_number(value) do if value > 0, do: true, else: false end def as_boolean(_value, default), do: default end