"""
end
@doc """
Shows the flash group with standard titles and content.
## Examples
<.flash_group flash={@flash} />
"""
attr :flash, :map, required: true, doc: "the map of flash messages"
def flash_group(assigns) do
~H"""
"""
end
@doc """
Creates a live region with the given role.
## Examples
<.live_region role="alert" />
<.live_region role="status" />
"""
def live_region(assigns) do
~H"""
"""
end
@doc """
Sends a message to be read by the screen reader by changing the text content of the live region
"""
def sr_message(js \\ %JS{}, message) do
JS.dispatch(js, "lb:set_text", to: "#live-region", detail: %{value: message})
end
@doc """
Wraps the given content in a modal dialog.
## Example
<.modal id="edit-modal" patch={...}>
<.live_component module={MyComponent} />
"""
attr :id, :string, required: true
attr :show, :boolean, default: false
attr :patch, :string, default: nil
attr :navigate, :string, default: nil
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def modal(assigns) do
~H"""
"""
end
@doc """
Shows a modal rendered with `modal/1`.
"""
def show_modal(js \\ %JS{}, id) do
js
|> JS.show(
to: "##{id}",
transition: {"ease-out duration-200", "opacity-0", "opacity-100"}
)
end
@doc """
Hides a modal rendered with `modal/1`.
"""
def hide_modal(js \\ %JS{}, id) do
js
|> JS.hide(
to: "##{id}",
transition: {"ease-in duration-200", "opacity-100", "opacity-0"}
)
|> JS.dispatch("click", to: "##{id}-return")
end
@doc """
Renders the confirmation modal for `with_confirm/3`.
"""
attr :id, :string, required: true
def confirm_modal(assigns) do
~H"""
<.modal id={@id} class="w-full max-w-xl" phx-hook="ConfirmModal" data-js-show={show_modal(@id)}>
"""
end
@doc """
Shows a confirmation modal before executing the given JS action.
The modal template must already be on the page, see `confirm_modal/1`.
## Options
* `:title` - title of the confirmation modal. Defaults to `"Are you sure?"`
* `:description` - content of the confirmation modal. Required
* `:confirm_text` - text of the confirm button. Defaults to `"Yes"`
* `:confirm_icon` - icon in the confirm button. Optional
* `:danger` - whether the action is destructive or regular. Defaults to `true`
* `:html` - whether the `:description` is a raw HTML. Defaults to `false`
* `:opt_out_id` - enables the "Don't show this message again"
checkbox. Once checked by the user, the confirmation with this
id is never shown again. Optional
## Examples
"""
def with_confirm(js \\ %JS{}, on_confirm, opts) do
opts =
Keyword.validate!(
opts,
[
:confirm_icon,
:description,
:opt_out_id,
title: "Are you sure?",
confirm_text: "Yes",
danger: true,
html: false
]
)
JS.dispatch(js, "lb:confirm_request",
detail: %{
on_confirm: Jason.encode!(on_confirm.ops),
title: opts[:title],
description: Keyword.fetch!(opts, :description),
confirm_text: opts[:confirm_text],
confirm_icon: opts[:confirm_icon],
danger: opts[:danger],
html: opts[:html],
opt_out_id: opts[:opt_out_id]
}
)
end
@doc """
Renders a popup menu that shows up on toggle click.
## Examples
<.menu id="my-menu">
<:toggle>
<:content>
"""
attr :id, :string, required: true
attr :disabled, :boolean, default: false, doc: "whether the menu is active"
attr :position, :atom,
default: :bottom_right,
values: [:top_left, :top_right, :bottom_left, :bottom_right]
attr :distant, :boolean,
default: false,
doc: "whether the menu should be further from the anchor element"
attr :secondary_click, :boolean,
default: false,
doc: "whether secondary click (usually right mouse click) should open the menu"
slot :toggle, required: true
slot :content, required: true
def menu(assigns) do
~H"""
<%= render_slot(@toggle) %>
"""
end
defp menu_content_class(:top_left), do: "menu__content--top-left"
defp menu_content_class(:top_right), do: "menu__content--top-right"
defp menu_content_class(:bottom_left), do: "menu__content--bottom-left"
defp menu_content_class(:bottom_right), do: "menu__content--bottom-right"
@doc """
A menu item that shows a submenu on hover.
This component should be used within `menu/1` content.
## Example
<.submenu>
<:content>
"""
slot :inner_block, required: true
slot :content, required: true
def submenu(assigns) do
~H"""
<%= render_slot(@inner_block) %>
"""
end
@doc """
Renders a text content skeleton.
"""
attr :empty, :boolean, default: false, doc: "if the source is empty"
attr :bg_class, :string, default: "bg-gray-200", doc: "the skeleton background color"
def content_skeleton(assigns) do
~H"""
<%= if @empty do %>
<% else %>
<% end %>
"""
end
@doc """
Renders a highlighted code snippet.
## Examples
<.code_preview
source_id="my-snippet"
language="elixir"
source="System.version()" />
"""
attr :source_id, :string, required: true
attr :language, :string, required: true
attr :source, :string, required: true
def code_preview(assigns) do
~H"""
<%= @source %>
"""
end
@doc """
Renders text with a tiny label.
## Examples
<.labeled_text label="Name">Sherlock Holmes
"""
attr :label, :string, required: true
attr :one_line, :boolean,
default: false,
doc: "whether to force the text into a single scrollable line"
slot :inner_block, required: true
def labeled_text(assigns) do
~H"""
<%= @label %>
<%= render_slot(@inner_block) %>
"""
end
@doc """
Renders a choice button that is either active or not.
## Examples
<.choice_button active={@tab == "my_tab"} phx-click="set_my_tab">
My tab
"""
attr :active, :boolean, required: true
attr :disabled, :boolean
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def choice_button(assigns) do
assigns =
assigns
|> assign_new(:disabled, fn -> assigns.active end)
~H"""
"""
end
# JS commands
@doc """
Toggles classes on elements.
"""
def toggle_class(js \\ %JS{}, names, opts \\ []) do
opts = Keyword.validate!(opts, [:to])
to = Keyword.fetch!(opts, :to)
names
|> String.split()
|> Enum.reduce(js, fn name, js ->
js
|> JS.remove_class(name, to: "#{to}.#{name}")
|> JS.add_class(name, to: "#{to}:not(.#{name})")
end)
end
end