defmodule LivebookWeb.Helpers do use Phoenix.Component alias LivebookWeb.Router.Helpers, as: Routes @doc """ Renders a component inside the `Livebook.ModalComponent` component. The rendered modal receives a `:return_to` option to properly update the URL when the modal is closed. """ def live_modal(component, opts) do {modal_opts, opts} = build_modal_opts(opts) modal_opts = [{:render_spec, {:component, component, opts}} | modal_opts] live_component(LivebookWeb.ModalComponent, modal_opts) end @doc """ Renders a live view inside the `Livebook.ModalComponent` component. See `live_modal/2` for more details. """ def live_modal(socket, live_view, opts) do {modal_opts, opts} = build_modal_opts(opts) modal_opts = [{:render_spec, {:live_view, socket, live_view, opts}} | modal_opts] live_component(LivebookWeb.ModalComponent, modal_opts) end defp build_modal_opts(opts) do path = Keyword.fetch!(opts, :return_to) {modal_class, opts} = Keyword.pop(opts, :modal_class) modal_opts = [ id: "modal", return_to: path, modal_class: modal_class ] {modal_opts, opts} end @doc """ Determines user platform based on the given *User-Agent* header. """ @spec platform_from_user_agent(String.t()) :: :linux | :mac | :windows | :other def platform_from_user_agent(user_agent) when is_binary(user_agent) do cond do linux?(user_agent) -> :linux mac?(user_agent) -> :mac windows?(user_agent) -> :windows true -> :other end end defp linux?(user_agent), do: String.match?(user_agent, ~r/Linux/) defp mac?(user_agent), do: String.match?(user_agent, ~r/Mac OS X/) defp windows?(user_agent), do: String.match?(user_agent, ~r/Windows/) @doc """ Returns path to specific process dialog within LiveDashboard. """ def live_dashboard_process_path(socket, pid) do pid_str = Phoenix.LiveDashboard.PageBuilder.encode_pid(pid) Routes.live_dashboard_path(socket, :page, node(), "processes", info: pid_str) end @doc """ Converts human-readable strings to strings which can be used as HTML element IDs (compatible with HTML5) At the same time duplicate IDs are enumerated to avoid duplicates """ @spec names_to_html_ids(list(String.t())) :: list(String.t()) def names_to_html_ids(names) do names |> Enum.map(&name_to_html_id/1) |> Enum.map_reduce(%{}, fn html_id, counts -> counts = Map.update(counts, html_id, 1, &(&1 + 1)) case counts[html_id] do 1 -> {html_id, counts} count -> {"#{html_id}-#{count}", counts} end end) |> elem(0) end defp name_to_html_id(name) do name |> String.trim() |> String.downcase() |> String.replace(~r/\s+/u, "-") end @doc """ Renders [Remix](https://remixicon.com) icon. ## Examples <.remix_icon icon="cpu-line" /> <.remix_icon icon="cpu-line" class="align-middle mr-1" /> """ def remix_icon(assigns) do assigns = assigns |> assign_new(:class, fn -> "" end) |> assign(:attrs, assigns_to_attributes(assigns, [:icon, :class])) ~H""" """ end @doc """ Renders a list of select input options with the given one selected. ## Examples <.select name="language" selected={@language} options={[en: "English", pl: "Polski", fr: "Français"]} /> """ def select(assigns) do ~H""" """ end @doc """ Renders a checkbox input styled as a switch. Also, a hidden input with the same name is rendered alongside the checkbox, so the submitted value is always either `"true"` or `"false"`. ## Examples <.switch_checkbox name="likes_cats" label="I very much like cats" checked={@likes_cats} /> """ def switch_checkbox(assigns) do assigns = assigns |> assign_new(:label, fn -> nil end) |> assign_new(:disabled, fn -> false end) |> assign_new(:class, fn -> "" end) |> assign( :attrs, assigns_to_attributes(assigns, [:label, :name, :checked, :disabled, :class]) ) ~H"""
<%= if @label do %> <%= @label %> <% end %>
""" 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 """ def choice_button(assigns) do assigns = assigns |> assign_new(:class, fn -> "" end) |> assign_new(:disabled, fn -> assigns.active end) |> assign(:attrs, assigns_to_attributes(assigns, [:active, :class, :disabled])) ~H""" """ end @doc """ Renders a highlighted code snippet. ## Examples <.code_preview source_id="my-snippet" language="elixir" source="System.version()" /> """ def code_preview(assigns) do ~H"""
<%= @source %>
""" end @doc """ Renders text with a tiny label. ## Examples <.labeled_text label="Name" text="Sherlock Holmes" /> """ def labeled_text(assigns) do ~H"""
<%= @label %> <%= @text %>
""" end defdelegate ansi_string_to_html(string), to: LivebookWeb.Helpers.ANSI defdelegate ansi_string_to_html_lines(string), to: LivebookWeb.Helpers.ANSI end