defmodule <%= @module_name %>.Components.UI.DataGrid do
@moduledoc """
Enhanced table with server-side sorting.
Ejected from PhiaUI — you own this copy. Customise freely.
## Example
<.data_grid>
<.data_grid_head sort_key="name" sort_dir={@sort_dir} on_sort="sort">
Name
<.data_grid_head>Actions
<.data_grid_body id="users" phx-update="stream">
<.data_grid_row :for={{id, user} <- @streams.users} id={id}>
<.data_grid_cell><%= user.name %>
## LiveView sort handler
def handle_event("sort", %{"key" => key, "dir" => dir}, socket) do
{:noreply, assign(socket, sort_key: key, sort_dir: String.to_existing_atom(dir))}
end
"""
use Phoenix.Component
import <%= @module_name %>.ClassMerger, only: [cn: 1]
import <%= @module_name %>.Components.UI.Icon, only: [icon: 1]
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def data_grid(assigns) do
~H"""
<%%= render_slot(@inner_block) %>
"""
end
attr :sort_key, :string, default: nil
attr :sort_dir, :atom, default: :none, values: [:none, :asc, :desc]
attr :on_sort, :string, default: "sort"
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def data_grid_head(assigns) do
~H"""
<%%= if @sort_key do %>
<%%= render_slot(@inner_block) %>
<.sort_icon dir={@sort_dir} />
<%% else %>
<%%= render_slot(@inner_block) %>
<%% end %>
"""
end
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def data_grid_body(assigns) do
~H"""
<%%= render_slot(@inner_block) %>
"""
end
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def data_grid_row(assigns) do
~H"""
<%%= render_slot(@inner_block) %>
"""
end
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def data_grid_cell(assigns) do
~H"""
<%%= render_slot(@inner_block) %>
"""
end
defp next_dir(:none), do: "asc"
defp next_dir(:asc), do: "desc"
defp next_dir(:desc), do: "none"
defp aria_sort(:none), do: "none"
defp aria_sort(:asc), do: "ascending"
defp aria_sort(:desc), do: "descending"
attr :dir, :atom, required: true, values: [:none, :asc, :desc]
defp sort_icon(%{dir: :none} = assigns) do
~H"""
<.icon name="chevrons-up-down" size={:sm} />
"""
end
defp sort_icon(%{dir: :asc} = assigns) do
~H"""
<.icon name="chevron-up" size={:sm} />
"""
end
defp sort_icon(%{dir: :desc} = assigns) do
~H"""
<.icon name="chevron-down" size={:sm} />
"""
end
end