149 lines
3.7 KiB
Elixir
149 lines
3.7 KiB
Elixir
defmodule Web.CoreComponents do
|
||
@moduledoc """
|
||
Provides core UI components.
|
||
"""
|
||
use Phoenix.Component
|
||
|
||
attr :class, :string, default: nil
|
||
attr :global, :global
|
||
slot :inner_block
|
||
|
||
def title(assigns) do
|
||
~H"""
|
||
<h1 class={["font-bold text-xl mb-3", @class]} {@global}>{render_slot(@inner_block)}</h1>
|
||
"""
|
||
end
|
||
|
||
attr :class, :string, default: nil
|
||
attr :global, :global
|
||
slot :inner_block
|
||
|
||
def subtitle(assigns) do
|
||
~H"""
|
||
<h2 class={["font-bold text-lg mb-2", @class]} {@global}>{render_slot(@inner_block)}</h2>
|
||
"""
|
||
end
|
||
|
||
attr :class, :string, default: nil
|
||
|
||
attr :global, :global,
|
||
include: ~w[navigate patch href replace method csrf_token download hreflang referrerpolicy rel target type]
|
||
|
||
slot :inner_block
|
||
|
||
def a(assigns) do
|
||
~H"""
|
||
<.link class={["hover:underline", @class]} {@global}>{render_slot(@inner_block)}</.link>
|
||
"""
|
||
end
|
||
|
||
attr :class, :string, default: nil
|
||
attr :type, :string, default: "button"
|
||
attr :global, :global
|
||
slot :inner_block
|
||
|
||
def button(assigns) do
|
||
~H"""
|
||
<button type={@type} class={["hover:underline", @class]} {@global}>
|
||
{render_slot(@inner_block)}
|
||
</button>
|
||
"""
|
||
end
|
||
|
||
attr :class, :string, default: nil
|
||
attr :field, Phoenix.HTML.FormField, required: true
|
||
attr :type, :string, default: "text"
|
||
attr :global, :global, include: ~w[required placeholder]
|
||
|
||
def input(%{type: "textarea"} = assigns) do
|
||
~H"""
|
||
<textarea
|
||
class={["px-2 py-1 border border-gray-400 rounded", @class]}
|
||
id={@field.id}
|
||
name={@field.name}
|
||
{@global}
|
||
>{@field.value}</textarea>
|
||
"""
|
||
end
|
||
|
||
def input(assigns) do
|
||
~H"""
|
||
<input
|
||
class={["px-2 py-1 border border-gray-400 rounded", @class]}
|
||
type={@type}
|
||
id={@field.id}
|
||
name={@field.name}
|
||
value={@field.value}
|
||
{@global}
|
||
/>
|
||
"""
|
||
end
|
||
|
||
@doc """
|
||
Renders a [Heroicon](https://heroicons.com).
|
||
|
||
Heroicons come in three styles – outline, solid, and mini.
|
||
By default, the outline style is used, but solid and mini may
|
||
be applied by using the `-solid` and `-mini` suffix.
|
||
|
||
You can customize the size and colors of the icons by setting
|
||
width, height, and background color classes.
|
||
|
||
Icons are extracted from the `deps/heroicons` directory and bundled within
|
||
your compiled app.css by the plugin in your `assets/tailwind.config.js`.
|
||
|
||
## Examples
|
||
|
||
<.icon name="hero-x-mark-solid" />
|
||
<.icon name="hero-arrow-path" class="ml-1 w-3 h-3 animate-spin" />
|
||
"""
|
||
attr :name, :string, required: true
|
||
attr :class, :string, default: nil
|
||
|
||
def icon(%{name: "hero-" <> _} = assigns) do
|
||
~H"""
|
||
<span class={[@name, @class]} />
|
||
"""
|
||
end
|
||
|
||
attr :format, :string, required: true
|
||
attr :value, :any, default: nil
|
||
attr :formatter, :atom, default: :default
|
||
attr :timezone, :string, default: "America/New_York"
|
||
attr :global, :global
|
||
|
||
def timex(%{value: nil} = assigns) do
|
||
~H"""
|
||
<time datetime="">--</time>
|
||
"""
|
||
end
|
||
|
||
def timex(%{value: value, timezone: timezone} = assigns) do
|
||
assigns =
|
||
assign_new(assigns, :local_value, fn ->
|
||
case value do
|
||
%DateTime{} = datetime ->
|
||
datetime
|
||
|
||
%NaiveDateTime{} = naive ->
|
||
naive
|
||
|> DateTime.from_naive!("Etc/UTC")
|
||
|> DateTime.shift_zone!(timezone)
|
||
end
|
||
end)
|
||
|
||
~H"""
|
||
<time
|
||
datetime={Timex.format!(@local_value, "{ISO:Extended}")}
|
||
title={Timex.format!(@local_value, "{Mshort} {D}, {YYYY}, {h12}:{m} {AM} {Zabbr}")}
|
||
{@global}
|
||
>
|
||
{Timex.format!(@local_value, @format, timex_formatter(@formatter))}
|
||
</time>
|
||
"""
|
||
end
|
||
|
||
defp timex_formatter(formatter) do
|
||
Module.concat(Timex.Format.DateTime.Formatters, :string.titlecase("#{formatter}"))
|
||
end
|
||
end
|