diff --git a/lib/doggo.ex b/lib/doggo.ex index dab8ef8e..d4e8f5f2 100644 --- a/lib/doggo.ex +++ b/lib/doggo.ex @@ -1823,6 +1823,151 @@ defmodule Doggo do """ end + @doc """ + Renders a simple table. + + ## Examples + + <.table id="pets" rows={@pets}> + <:col :let={p} label="name"><%= p.name %> + <:col :let={p} label="age"><%= p.age %> + + """ + attr :id, :string, required: true + + attr :items, :list, + required: true, + doc: "The list of items to be displayed in rows." + + attr :caption, :string, + default: nil, + doc: "Content for the `` element." + + attr :row_id, :any, + default: nil, + doc: """ + Overrides the default function that retrieves the row ID from a stream item. + """ + + attr :row_click, JS, + default: nil, + doc: """ + Sets the `phx-click` function attribute for each row `td`. Expects to be a + function that receives a row item as an argument. This does not add the + `phx-click` attribute to the `action` slot. + + Example: + + ```elixir + row_click={&JS.navigate(~p"/users/\#{&1}")} + ``` + """ + + attr :row_item, :any, + default: &Function.identity/1, + doc: """ + This function is called on the row item before it is passed to the :col + and :action slots. + """ + + slot :col, + required: true, + doc: """ + For each column to render, add one `<:col>` element. + + ```elixir + <:col :let={pet} label="Name" field={:name} col_style="width: 20%;"> + <%= pet.name %> + + ``` + + Any additional assigns will be added as attributes to the `` elements. + + """ do + attr :label, :any, doc: "The content for the header column." + + attr :col_attrs, :string, + doc: """ + If set, a `` element is rendered and the attributes are added + to the `` element of the respective column. + """ + end + + slot :action, + doc: """ + The slot for showing user actions in the last table column. These columns + do not receive the `row_click` attribute. + + + ```elixir + <:action :let={user}> + <.link navigate={~p"/users/\#{user}"}>Show + + ``` + """ do + attr :label, :string, doc: "The content for the header column." + + attr :col_attrs, :string, + doc: """ + If set, a `` element is rendered and the attributes are added + to the `` element of the respective column. + """ + end + + slot :foot, + default: nil, + doc: """ + You can optionally add a `foot`. The inner block will be rendered inside + a `tfoot` element. + + + <:foot> + Total: <%= @total %> + + + """ + + def table(assigns) do + assigns = + with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do + assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end) + end + + ~H""" +
+ + + + + + + + + + + + + "-tbody"} + phx-update={match?(%Phoenix.LiveView.LiveStream{}, @rows) && "stream"} + > + + + + + + <%= render_slot(@foot) %> +
<%= @caption %>
<%= col[:label] %><%= action[:label] %>
+ <%= render_slot(col, @row_item.(row)) %> + + <%= render_slot(action, @row_item.(row)) %> +
+
+ """ + end + @doc """ Renders a drawer with a `brand`, `top`, and `bottom` slot.