defmodule LayoutBuilder do use Phoenix.LiveComponent use PetalComponents import LayoutBuilder.Gettext alias LayoutBuilder.Layout.Layout @moduledoc """ `LayoutBuilder` allows you to create a %Layout.Layout{} containing %Layout.Row{} and %Layout.Row{}. """ @doc """ LayoutBuilder component ## Examples <.layout_builder /> """ slot :content, doc: "Content to show inside each col" do attr :class, :string, doc: "Custom classes to add" end attr :title, :string, default: "h2", doc: " title level", values: ["h1", "h2", "h3", "h4", "h5", "h6"] attr :title_class, :string, default: "", doc: "classes to add to ", examples: ["text-2xl font-medium"] attr :class, :string, default: "", doc: "classes to pass to layout builder", examples: ["mt-6"] attr :row_class, :string, default: "flex", doc: "classes to pass to layout builder", examples: ["mt-6"] attr :edit_layout, :boolean, default: true, doc: "show buttons to add / remove cols and rows from layout builder and show background colors" attr :layout, Layout, required: true, doc: "layout built", examples: [%Layout{}] def render(assigns) do assigns = assigns |> assign_new(:above, fn -> nil end) ~H"""
<%= case @title do %> <% "h1" -> %>

<.title/>

<% "h2" -> %>

<.title/>

<% "h3" -> %>

<.title/>

<% "h4" -> %>

<.title/>

<% "h5" -> %>
<.title/>
<% "h6" -> %>
<.title/>
<% end %>
<%= for row <- @layout.rows do %> <%= if @above do %>
<%= render_slot(@above, row) %>
<% end %>
"#{@row_class} gap-x-3 p-3"}> <%= for col <- row.cols do %>
Map.get(Enum.at(@content, 0), :class, "flex-1")}> <%= render_slot(@content, col) %>
<% end %> <%= if @edit_layout do %> <.button color="gray" class="w-20 h-12" phx-value-row={row.id} phx-click="add_column" phx-target={@myself}> <% end %>
<% end %> <%= if @edit_layout do %> <.button color="gray" class="w-full h-12" phx-click="add_row" phx-target={@myself}> <% end %>
""" end @spec handle_event(String.t(), map, Elixir.Phoenix.LiveView.Socket.t()) :: {:noreply, Elixir.Phoenix.LiveView.Socket.t()} def handle_event("add_column", %{"row" => id}, socket) do row = Enum.find(socket.assigns.layout.rows, fn row -> row.id == id end) layout = Layout.add_col(socket.assigns.layout, row) send(self(), %{layout: layout}) {:noreply, socket} end def handle_event("add_row", _, socket) do layout = Layout.add_row(socket.assigns.layout) send(self(), %{layout: layout}) {:noreply, assign(socket, :layout, layout)} end defp title(assigns) do ~H""" <%= gettext("Layout builder") %> """ end defp classes do "text-sm font-medium text-gray-500 dark:text-gray-400" end end