Packages
petal_components
0.10.4
4.6.2
4.6.1
4.6.0
4.5.0
4.4.0
4.3.0
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.12
4.0.11
4.0.10
4.0.6
4.0.5
4.0.4
4.0.3
4.0.1
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.9.3
2.9.2
retired
2.9.1
retired
2.9.0
retired
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.1
1.7.0
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.1
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.8
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.1
0.2.0
0.1.0
Shadcn-style Phoenix LiveView components that AI assistants can actually use. Pair with the MCP server so AI coding tools can inspect the real component API.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/heroicons/generate.ex
defmodule Mix.Tasks.Heroicons.Generate do
use Mix.Task
@shortdoc "Convert source SVG files into heex components. Run `git clone https://github.com/tailwindlabs/heroicons.git` first."
def run(_) do
Enum.each(["outline", "solid"], &loop_directory/1)
Mix.Task.run("format")
end
defp loop_directory(folder) do
src_path = "./heroicons/optimized/#{folder}/"
namespace = "Heroicons.#{String.capitalize(folder)}"
file_content = """
defmodule PetalComponents.#{namespace} do
use Phoenix.Component
@moduledoc \"\"\"
Icon name can be the function or passed in as a type eg.
<PetalComponents.Heroicons.Solid.home class="w-6 h-6" />
<PetalComponents.Heroicons.Solid.render type="home" class="w-6 h-6" />
<PetalComponents.Heroicons.Outline.home class="w-6 h-6" />
<PetalComponents.Heroicons.Outline.render type="home" class="w-6 h-6" />
\"\"\"
def render(assigns) do
icon_name = assigns.icon
apply(__MODULE__, icon_name, [assigns])
end
"""
functions_content =
src_path
|> File.ls!()
|> Enum.filter(&(Path.extname(&1) == ".svg"))
|> Enum.map(&create_component(src_path, &1))
|> Enum.join("\n\n")
file_content =
file_content <>
functions_content <>
"""
end
"""
dest_path = "./lib/petal_components/icons/heroicons/#{folder}.ex"
unless File.exists?(dest_path) do
File.mkdir_p("./lib/petal_components/icons/heroicons")
end
File.write!(dest_path, file_content)
end
defp create_component(src_path, filename) do
svg_content =
File.read!(Path.join(src_path, filename))
|> String.trim()
|> String.replace(~r/<svg /, "<svg class={@class} {@extra_attributes} ")
build_component(filename, svg_content)
end
defp function_name(current_filename) do
current_filename
|> Path.basename(".svg")
|> String.replace("-", "_")
end
defp build_component(filename, svg) do
"""
def #{function_name(filename)}(assigns) do
assigns = assigns
|> assign_new(:class, fn -> "h-6 w-6" end)
|> assign_new(:extra_attributes, fn ->
Map.drop(assigns, [:class])
end)
~H\"\"\"
#{svg}
\"\"\"
end
"""
end
end