Current section

Files

Jump to
moon lib moon design circular_progress.ex
Raw

lib/moon/design/circular_progress.ex

defmodule Moon.Design.CircularProgress do
@moduledoc false
use Moon.StatelessComponent
prop(bg_color, :css_class, default: "stroke-trunks/[.24]")
prop(progress_color, :css_class, default: "stroke-piccolo")
prop(size, :string, values: ["2xs", "xs", "sm", "md", "lg"], default: "md")
prop(value, :decimal, default: 0)
prop(class, :css_class)
prop(testid, :string)
prop(id, :string)
def render(assigns) do
~F"""
<svg
{=@id}
style={get_style(width: "1em", height: "1em", vertical_align: "middle")}
viewBox={"0 0 #{viewbox_width()} #{viewbox_height()}"}
font-size={get_circular_size(@size)}
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={@value}
data-testid={@testid}
{=@class}
role="progressbar"
>
<path style={get_style(fill_opacity: 0)} class={"stroke-[0.5rem] #{@bg_color}"} d={get_d()} />
<path
style={get_style(
fill_opacity: 0,
stroke_linecap: "round",
"stroke-dashoffset": "#{gaplength(@value)}px",
"stroke-dasharray": "#{circumference()}px #{circumference()}px"
)}
class={"stroke-[0.5rem] rtl:-scale-x-100 rtl:translate-x-full #{@progress_color} "}
d={get_d()}
/>
</svg>
"""
end
def get_circular_size(size) do
case size do
"2xs" -> "1rem"
"xs" -> "1.5rem"
"sm" -> "2rem"
"md" -> "2.5rem"
"lg" -> "3rem"
end
end
defp get_d() do
"""
M #{viewbox_center_x()},#{viewbox_center_y()}
m 0,-#{path_radius()}
a #{path_radius()},#{path_radius()} 0 1 1 0,#{2 * path_radius()}
a #{path_radius()},#{path_radius()} 0 1 1 0,-#{2 * path_radius()}
"""
end
defp viewbox_width(), do: 100
defp viewbox_height(), do: 100
defp viewbox_center_x(), do: 50
defp viewbox_center_y(), do: 50
defp path_radius(), do: (viewbox_height() - 8) / 2
defp circumference(), do: pi() * 2 * path_radius()
defp gaplength(value), do: (100 - value) * circumference() / 100
defp pi(), do: 3.14159
end