defmodule Heroicons do @moduledoc "Defines a convenience macro `icon/1`." @doc """ Use this macro in Phoenix HEEX templates to generate Heroicons. The name of the icon can be defined using the `name` attribute or (deprecated) `type` attribute. The style of the icon is defined by the `solid`, `outline`, or `mini` boolean attribute or a (deprecated) `style` attribute. ## Attributes - `name` - icon name. Valid names are found at [this url](https://heroicons.com). - `solid` - use solid fill 24x24 icon. - `outline` - use outline fill 24x24 icon (this is the default). - `mini` - use mini size (20x20) for elements like buttons, form elements. - `title` - when defined, include the title value in the SVG. - `class` - add class attribute to the SVG. - `rest` - other attributes to add to the SVG. ## Example ``` ~H""" \""" ``` """ defmacro icon(assigns) do quote do {name, assigns} = case Map.fetch(unquote(assigns), :name) do {:ok, name} -> {name, Map.delete(unquote(assigns), :name)} :error -> Map.pop!(unquote(assigns), :type) end {style, assigns} = Map.pop(assigns, :style) icon = Heroicons.to_atom(name) {mod, assigns} = case style do nil -> cond do assigns[:solid] -> {Heroicons.Solid, Map.delete(assigns, :solid)} assigns[:outline] -> {Heroicons.Outline, Map.delete(assigns, :outline)} assigns[:mini] -> {Heroicons.Mini, Map.delete(assigns, :mini)} true -> raise ArgumentError, message: "Missing style|solid|outline|mini attribute" end "solid" -> {Heroicons.Solid, assigns} "outline" -> {Heroicons.Outline, assigns} "mini" -> {Heroicons.Mini, assigns} end Code.loaded?(mod) || ({:module, ^mod} = :code.load_file(mod)) :erlang.function_exported(mod, icon, 1) || raise ArgumentError, message: "Invalid Heroicon type '#{name}': no function #{inspect(mod)}.#{icon}/1" apply(mod, icon, [assigns]) end end @doc false def to_atom(s) when is_binary(s), do: s |> String.replace("-", "_") |> String.to_existing_atom() def to_atom(s) when is_atom(s), do: s end defmodule Heroicons.Helpers.Svg do @moduledoc false # SVG helper component use Phoenix.Component attr :title, :string, default: nil attr :class, :string, default: nil attr :rest, :global, doc: "HTML attributes for the svg container", include: ~w(fill stroke stroke-width) attr :paths, :string, required: true @doc false def icon(assigns) do assigns = case assigns[:class] do nil -> assigns val -> put_in(assigns, [:rest, :class], val) end ~H""" """ end end