Skip to main content

lib/pdf/component/row.ex

defmodule Pdf.Component.Row do
  @moduledoc """
  Row component for PDF documents.

  Distributes content horizontally in columns by weight.
  Operates at Document level.

  ## Example

      doc
      |> Pdf.Component.Row.render({50, 700}, {400, 80}, [
        {1, fn doc, area -> Pdf.text_at(doc, {area.x, area.y - 14}, "Col 1") end},
        {2, fn doc, area -> Pdf.text_at(doc, {area.x, area.y - 14}, "Col 2") end}
      ], gap: 10)
  """

  @doc """
  Render a horizontal row at `{x, y}` with size `{w, h}`.

  `columns` is a list of `{weight, callback}` tuples where each callback
  receives `(doc, %{x, y, width, height})`.

  ## Options

  - `:gap` — space between columns (default `0`)
  """
  def render(doc, {x, y}, {w, h}, columns, opts \\ []) when is_list(columns) do
    gap = Keyword.get(opts, :gap, 0)
    total_weight = columns |> Enum.map(&elem(&1, 0)) |> Enum.sum()
    gap_total = gap * max(length(columns) - 1, 0)
    available_w = w - gap_total

    {doc, _x} =
      Enum.reduce(columns, {doc, x}, fn {weight, callback}, {doc, col_x} ->
        col_w = available_w * (weight / total_weight)
        doc = callback.(doc, %{x: col_x, y: y, width: col_w, height: h})
        {doc, col_x + col_w + gap}
      end)

    doc
  end
end