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 %> <%% 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