Files
phosphoricons/lib/heroicons/generator.ex

125 lines
2.9 KiB
Elixir
Raw Normal View History

defmodule Heroicons.Generator do
2022-09-02 13:49:03 -04:00
@moduledoc false
defmacro __using__(icon_dir: icon_dir) do
icon_paths =
Path.absname(icon_dir, :code.priv_dir(:heroicons))
|> Path.join("*.svg")
|> Path.wildcard()
require Phoenix.Component
for path <- icon_paths do
2022-09-02 18:57:26 -04:00
relative_path = Path.relative_to(path, :code.priv_dir(:heroicons))
generate(relative_path)
end
end
@doc false
def generate(path) do
2022-09-02 05:48:50 -04:00
name = Heroicons.Generator.name(path)
quote do
2022-09-02 18:57:26 -04:00
@doc Heroicons.Generator.doc(unquote(name), unquote(path))
2022-09-02 05:48:50 -04:00
def unquote(name)(assigns_or_opts \\ [])
def unquote(name)(assigns) when is_map(assigns) do
Heroicons.Generator.icon_component(unquote(path), assigns)
end
def unquote(name)(opts) when is_list(opts) do
Heroicons.Generator.icon_function(unquote(path), opts)
end
end
end
@doc false
def name(path) do
Path.basename(path, ".svg")
|> String.replace("-", "_")
|> String.to_atom()
end
@doc false
2022-09-02 18:57:26 -04:00
def doc(name, path) do
2022-09-02 05:48:50 -04:00
"""
2022-09-02 18:57:26 -04:00
![](assets/#{path}) {: width=24px}
2022-09-02 13:21:32 -04:00
## Examples
2022-09-02 13:21:32 -04:00
Use as a `Phoenix.Component`
2022-09-02 13:21:32 -04:00
<.#{name} />
2022-09-02 18:57:26 -04:00
<.#{name} class="w-6 h-6 text-gray-500" />
2022-09-02 13:21:32 -04:00
or as a function
2022-09-02 13:21:32 -04:00
<%= #{name}() %>
2022-09-02 19:03:41 -04:00
<%= #{name}(class: "w-6 h-6 text-gray-500") %>
"""
2022-09-02 05:48:50 -04:00
end
2022-09-02 05:48:50 -04:00
if function_exported?(Phoenix.Component, :assigns_to_attributes, 2) do
@assign_mod Phoenix.Component
@assigns_to_attrs_mod Phoenix.Component
else
@assign_mod Phoenix.LiveView
@assigns_to_attrs_mod Phoenix.LiveView.Helpers
end
2022-09-02 05:48:50 -04:00
@doc false
def icon_component(path, assigns) when is_map(assigns) do
attrs = @assigns_to_attrs_mod.assigns_to_attributes(assigns)
assigns = @assign_mod.assign(assigns, :attrs, attrs)
2022-09-02 21:01:48 -04:00
dynamic = fn track_changes? ->
changed =
case assigns do
%{__changed__: changed} when track_changes? -> changed
_ -> nil
end
attrs =
case Phoenix.LiveView.Engine.changed_assign?(changed, :attrs) do
true -> elem(Phoenix.HTML.attributes_escape(assigns.attrs), 1)
false -> nil
end
[attrs]
end
2022-09-02 07:20:50 -04:00
2022-09-02 21:01:48 -04:00
{icon_body, fingerprint} = Heroicons.Cache.fetch_icon(path)
%Phoenix.LiveView.Rendered{
static: [
"<svg",
icon_body
],
dynamic: dynamic,
fingerprint: fingerprint,
root: true
}
2022-09-02 05:48:50 -04:00
end
@doc false
def icon_function(path, opts) when is_list(opts) do
attrs =
for {k, v} <- opts do
safe_k =
k |> Atom.to_string() |> String.replace("_", "-") |> Phoenix.HTML.Safe.to_iodata()
safe_v = v |> Phoenix.HTML.Safe.to_iodata()
{:safe, [?\s, safe_k, ?=, ?", safe_v, ?"]}
end
2022-09-02 05:48:50 -04:00
2022-09-02 21:01:48 -04:00
{icon_body, _fingerprint} = Heroicons.Cache.fetch_icon(path)
2022-09-02 05:48:50 -04:00
{:safe,
[
"<svg",
Phoenix.HTML.Safe.to_iodata(attrs),
2022-09-02 21:01:48 -04:00
icon_body
2022-09-02 05:48:50 -04:00
]}
end
end