Current section

Files

Jump to
phoenix_duskmoon lib phoenix_duskmoon component table.ex
Raw

lib/phoenix_duskmoon/component/table.ex

defmodule PhoenixDuskmoon.Component.Table do
@moduledoc """
Render table.
"""
use PhoenixDuskmoon.Component, :html
@doc """
Generates a table.
## Examples
```heex
<.dm_table data={[
%{
name: "Shmi Skywalker",
portrayal: "Pernilla August (Episodes I-II)"
},
%{
name: "Luke Skywalker",
portrayal: "Mark Hamill (Episodes IV-IX, The Mandalorian, The Book of Boba Fett)"}
]}
>
<:caption>Skywalker House</:catption>
<:col :let={r} label="Name" label_class="text-teal-600" class="text-teal-400">
<%= r.name %>
</:col>
<:col :let={r} label="Portrayal">
<%= r.portrayal %>
</:col>
</.dm_table>
```
"""
@doc type: :component
attr(:id, :any,
default: false,
doc: """
html attribute id
"""
)
attr(:class, :any,
default: "",
doc: """
html attribute class
"""
)
attr(:border, :boolean,
default: false,
doc: """
show table border
"""
)
attr(:data, :list,
default: [],
doc: """
table data list
"""
)
attr(:stream, :boolean,
default: false,
doc: "stream data"
)
slot(:caption,
required: false,
doc: """
render a caption of table.
Example
```heex
<:caption>
Table information
</:caption>
```
"""
) do
attr(:id, :any, doc: "table caption id")
attr(:class, :any, doc: "table caption class")
end
slot(:col,
required: false,
doc: """
render a column of table.
Example
```heex
<:col :let={r} label="Name">
<%= r.name %>
</:col>
```
"""
) do
attr(:label, :string, doc: "table column title")
attr(:label_class, :any, doc: "table column title title")
attr(:class, :any, doc: "table row column class")
end
slot(:expand,
required: false,
doc: """
render a one column row after each row of table.
Example
```heex
<:expand :let={r} label="Name">
<pre>
<%= r.description %>
</pre>
</:expand>
```
"""
) do
attr(:id, :any, doc: "table row expand id")
attr(:class, :any, doc: "table row expand class")
end
def dm_table(assigns) do
~H"""
<table
role="table"
id={@id}
class={[
"table border-collapse border-spacing-0",
if(@border, do: "border"),
@class,
]}
>
<caption
:for={caption <- @caption}
role="caption"
id={Map.get(caption, :id, false)}
class={Map.get(caption, :class, "")}
><%= render_slot(caption) %></caption>
<thead role="row-group" class="hidden md:table-header-group sticky top-0">
<tr role="row" class="table-row table-header-row">
<th
:for={col <- @col}
role="columnheader"
class={[
"font-bold",
if(@border, do: "border"),
Map.get(col, :label_class, "")
]}
><%= col.label %></th>
</tr>
</thead>
<%= if @stream do %>
<tbody role="row-group" id={"@id-stream-body"} phx-update="stream">
<tr
:for={{row_id, row} <- @data}
role="row"
id={row_id}
class={"table-row"}
>
<td
:for={col <- @col}
data-label={col.label}
role="cell"
class={[
if(@border, do: "border"),
Map.get(col, :class, "")
]}
><%= render_slot(col, row) %></td>
</tr>
</tbody>
<% else %>
<tbody role="row-group">
<%= for row <- @data do %>
<tr
role="row"
class={"table-row"}
>
<td
:for={col <- @col}
data-label={col.label}
role="cell"
class={[
if(@border, do: "border"),
Map.get(col, :class, "")
]}
><%= render_slot(col, row) %></td>
</tr>
<tr
role="row"
class={[
"table-row-expand",
Map.get(expand, :class, "")
]}
:if={length(@expand) > 0}
:for={expand <- @expand}
id={Map.get(expand, :id, false)}
>
<td
colspan={length(@col)}
role="cell"
class={[
"p-0",
if(@border, do: "border"),
]}
><%= render_slot(expand, row) %></td>
</tr>
<% end %>
</tbody>
<% end %>
</table>
"""
end
end