<table id={@id} class={@class}>
  <thead class={@header_class}>
    <tr>
      <th :for={header <- @meta.headers} data-test-table-header={header.id}>
        <%= Map.get(header, :label, header.id) %>
        <%= if Map.get(header, :sort, true) do %>
          <%= if @sort_control do %>
            <%= render_slot(@sort_control, {column_sort_order(@sort, header.id), header.id, @myself}) %>
          <% else %>
            <.sort_control direction={column_sort_order(@sort, header.id)} phx-click="sort" phx-value-header={header.id} phx-target={@myself} />
          <% end %>
        <% end %>
        &nbsp;
        <%= if @filter_control do %>
          <%= render_slot(@filter_control, {Map.has_key?(@filter, header.id), header.id, @myself}) %>
        <% else %>
          <.filter_control active?={Map.has_key?(@filter, header.id)} phx-click="filter_toggle" phx-value-header={header.id} phx-target={@myself} />
        <% end %>
      </th>
    </tr>
    <tr :if={map_size(@filter) > 0}>
      <th :for={header <- @meta.headers} data-test-table-header-filter={header.id}>
        <input :if={Map.has_key?(@filter, header.id)} type="text" phx-keyup="filter_change" phx-value-header={header.id} phx-target={@myself} value={Map.fetch!(@filter, header.id)} />
      </th>
    </tr>
  </thead>

  <tbody class={@body_class}>
    <tr :for={row <- @processed_rows}>
      <td :for={header <- @meta.headers}>
        <%= if Map.has_key?(header, :render) do %>
          <%= @engine_module.component(
            header.render,
            [value: row[header.id]],
            {__ENV__.module, __ENV__.function, __ENV__.file, __ENV__.line}) %>
        <% else %>
          <%= row[header.id] %>
        <% end %>
      </td>
    </tr>
  </tbody>
</table>
