defmodule SigmaKit.Components.Table do use Phoenix.LiveComponent import SigmaKit.Components.Icons, only: [icon: 1] import SigmaKit.Components.Buttons, only: [action_dropdown: 1] @doc """ Renders a table with generic styling. ## Examples <.table id="users" rows={@users}> <:col :let={user} label="id">{user.id} <:col :let={user} label="username">{user.username} """ attr :id, :string, required: true, doc: "the unique id of the table" attr :rows, :list, required: true, doc: "A list of row data to render" attr :row_id, :any, default: nil, doc: "the function for generating the row id" attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row" attr :alternate, :boolean, default: false, doc: "whether to alternate row colors" attr :paginate, :boolean, default: false, doc: "whether to show pagination" attr :page_number, :integer, doc: "the current page number" attr :total_pages, :integer, doc: "the total number of pages" attr :page_size, :integer, doc: "the number of rows per page" attr :total_entries, :integer, doc: "the total number of entries" attr :row_item, :any, default: &Function.identity/1, doc: "the function for mapping each row before calling the :col and :action slots" slot :col, required: true, doc: "A column to render for the table" do attr :label, :string, doc: "The label for the column header" attr :shrink, :boolean, doc: "Whether to shrink the column to fit the content" attr :expand, :boolean, doc: "Whether to expand the column to fit the content" attr :class, :any, doc: "Additional CSS classes that can be added to column cells" end slot :action, doc: "An action item to present in a dropdown menu" do attr :label, :string, doc: "The label for the menu item" attr :event, :any, doc: "The phx-click event for the menu item" attr :target, :string, doc: "The phx-target for the menu item" attr :icon, :string, doc: "The icon for the menu item" attr :divider, :boolean, doc: "Whether to this item is a divider" end def table(%{rows: %Scrivener.Page{}} = assigns) do assigns |> assign(rows: assigns.rows.entries) |> assign(page_number: assigns.rows.page_number) |> assign(total_pages: assigns.rows.total_pages) |> assign(total_entries: assigns.rows.total_entries) |> assign(page_size: assigns.rows.page_size) |> assign(paginate: true) |> table() end 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"""
| {col[:label]} | |
|---|---|
|
{render_slot(col, @row_item.(row))}
|
<.action_dropdown id={"actions-#{@id}-#{(@row_id && @row_id.(row)) || row_idx}"} class={[ "text-black rounded", @row_click && "group-hover:bg-primary-100" ]} > <:action :for={action <- @action} label={action[:label]} icon={action[:icon]} event={row_click(row, action[:event])} target={action[:target]} divider={action[:divider]} value_id={row.id} /> |