defmodule Doggo do @moduledoc """ Collection of Phoenix Components. """ use Phoenix.Component alias Phoenix.HTML.Form alias Phoenix.LiveView.JS @fills [:solid, :outline, :text] @ratios [ {1, 1}, {3, 2}, {2, 3}, {4, 3}, {3, 4}, {5, 4}, {4, 5}, {16, 9}, {9, 16} ] @shapes [:circle, :pill] @sizes [:small, :normal, :medium, :large] @skeleton_types [ :text_line, :text_block, :image, :circle, :rectangle, :square ] @variants [:primary, :secondary, :info, :success, :warning, :danger] ## Components @doc """ Renders a set of headings that control the visibility of their content sections. ## Example ```heex <:section title="Golden Retriever">

Friendly, intelligent, great with families. Origin: Scotland. Needs regular exercise.

<:section title="Siberian Husky">

Energetic, outgoing, distinctive appearance. Origin: Northeast Asia. Loves cold climates.

<:section title="Dachshund">

Playful, stubborn, small size. Origin: Germany. Enjoys sniffing games.

``` """ @doc type: :component @doc since: "0.5.0" attr :id, :string, required: true attr :expanded, :atom, values: [:all, :none, :first], default: :all, doc: """ Defines how the accordion sections are initialized. - `:all` - All accordion sections are expanded by default. - `:none` - All accordion sections are hidden by default. - `:first` - Only the first accordion section is expanded by default. """ attr :heading, :string, default: "h3", values: ["h2", "h3", "h4", "h5", "h6"], doc: """ The heading level for the section title (trigger). """ attr :class, :any, default: [], doc: "Additional CSS classes. Can be a string or a list of strings." attr :rest, :global, doc: "Any additional HTML attributes." slot :section, required: true do attr :title, :string end def accordion(assigns) do ~H"""
<.dynamic_tag name={@heading}>
""" end defp accordion_section_expanded?(_, :all), do: true defp accordion_section_expanded?(_, :none), do: false defp accordion_section_expanded?(1, :first), do: true defp accordion_section_expanded?(_, :first), do: false defp toggle_accordion_section(id, index) when is_binary(id) and is_integer(index) do %JS{} |> JS.toggle_attribute({"aria-expanded", "true", "false"}, to: "##{id}-trigger-#{index}" ) |> JS.toggle_attribute({"hidden", "hidden"}, to: "##{id}-section-#{index}") end @doc """ The action bar offers users quick access to primary actions within the application. It is typically positioned to float above other content. > #### In Development {: .warning} > > The necessary JavaScript for making this component fully functional and > accessible will be added in a future version. > > **Missing features** > > - Roving tabindex > - Move focus with arrow keys ## Example ```heex <:item label="Edit" on_click={JS.push("edit")}> <:item label="Move" on_click={JS.push("move")}> <:item label="Archive" on_click={JS.push("archive")}> ``` """ @doc type: :component @doc since: "0.1.0" attr :class, :any, default: [], doc: "Additional CSS classes. Can be a string or a list of strings." attr :rest, :global, doc: "Any additional HTML attributes." slot :item, required: true do attr :label, :string, required: true attr :on_click, JS, required: true end def action_bar(assigns) do ~H""" """ end @doc """ Renders an alert dialog that requires the immediate attention and response of the user. This component is meant for situations where critical information must be conveyed, and an explicit response is required from the user. It is typically used for confirmation dialogs, warning messages, error notifications, and other scenarios where an immediate decision is necessary. For non-critical dialogs, such as those containing forms or additional information, use `Doggo.modal/1` instead. ## Usage ```heex <:title>End Training Session Early?

Are you sure you want to end the current training session with Bella? She's making great progress today!

<:footer> Yes, end session No, continue training
``` To open the dialog, use the `show_modal/1` function. ```heex show ``` ## CSS To hide the modal when the `open` attribute is not set, use the following CSS styles: ```css dialog.alert-dialog:not([open]), dialog.alert-dialog[open="false"] { display: none; } ``` ## Semantics While the `showModal()` JavaScript function is typically recommended for managing modal dialog semantics, this component utilizes the `open` attribute to control visibility. This approach is chosen to eliminate the need for library consumers to add additional JavaScript code. To ensure proper modal semantics, the `aria-modal` attribute is added to the dialog element. """ @doc type: :component @doc since: "0.5.0" attr :id, :string, required: true attr :open, :boolean, default: false, doc: "Initializes the dialog as open." attr :on_cancel, JS, default: %JS{}, doc: """ An additional `Phoenix.LiveView.JS` command to execute when the dialog is canceled. This command is executed in addition to closing the dialog. If you only want the dialog to be closed, you don't have to set this attribute. """ attr :dismissable, :boolean, default: false, doc: """ When set to `true`, the dialog can be dismissed by clicking a close button or by pressing the escape key. """ attr :close_label, :string, default: "Close", doc: "Aria label for the close button." slot :title, required: true slot :inner_block, required: true, doc: "The modal body." slot :close, doc: "The content for the 'close' link. Defaults to the word 'close'." slot :footer attr :class, :any, default: [], doc: "Additional CSS classes. Can be a string or a list of strings." attr :rest, :global, doc: "Any additional HTML attributes." def alert_dialog(assigns) do ~H""" <.focus_wrap id={"#{@id}-container"} class="alert-dialog-container" phx-window-keydown={@dismissable && JS.exec("data-cancel", to: "##{@id}")} phx-key={@dismissable && "escape"} phx-click-away={@dismissable && JS.exec("data-cancel", to: "##{@id}")} >

<%= render_slot(@title) %>

<%= render_slot(@inner_block) %>
<%= render_slot(@footer) %>
""" end @doc """ The app bar is typically located at the top of the interface and provides access to key features and navigation options. ## Usage ```heex <:navigation label="Open menu" on_click={JS.push("toggle-menu")}> <:action label="Search" on_click={JS.push("search")}> <:action label="Like" on_click={JS.push("like")}> ``` """ @doc type: :navigation @doc since: "0.1.0" attr :title, :string, default: nil, doc: "The page title. Will be set as `h1`." attr :class, :any, default: [], doc: "Additional CSS classes. Can be a string or a list of strings." attr :rest, :global, doc: "Any additional HTML attributes." slot :navigation, doc: """ Slot for a single button left of the title, typically used for a menu button that toggles a drawer, or for a back link. """ do attr :label, :string, required: true attr :on_click, :any, required: true, doc: "Event name or `Phoenix.LiveView.JS` command." end slot :action, doc: "Slot for action buttons right of the title." do attr :label, :string, required: true attr :on_click, :any, required: true, doc: "Event name or `Phoenix.LiveView.JS` command." end def app_bar(assigns) do ~H"""
<.link :for={navigation <- @navigation} phx-click={navigation.on_click} title={navigation.label} > <%= render_slot(navigation) %>

<%= @title %>

<.link :for={action <- @action} phx-click={action.on_click} title={action.label} > <%= render_slot(action) %>
""" end @doc """ Renders a badge, typically used for drawing attention to elements like notification counts. ## Examples ```heex 8 ``` """ @doc type: :component @doc since: "0.3.0" attr :size, :atom, values: @sizes, default: :normal attr :variant, :atom, values: [nil | @variants], default: nil slot :inner_block, required: true def badge(assigns) do ~H""" <%= render_slot(@inner_block) %> """ end @doc """ Renders a navigation that sticks to the bottom of the screen. ## Example ```heex <:item label="Profile" navigate={~p"/pets/\#{@pet}"} value={Profile} > ``` """ @doc type: :navigation @doc since: "0.3.0" attr :label, :string, default: nil, doc: """ Label for the `