defmodule Pdf.Component.Signature do @moduledoc """ Signature component for PDF documents. Renders a signature line with name, title/role, and optional date. Useful for contracts, letters, and formal documents. ## Examples doc |> Pdf.Component.Signature.render({50, 200}, %{ name: "John Doe", title: "CEO, Acme Corp" }) doc |> Pdf.Component.Signature.render({50, 200}, %{ name: "Jane Smith", title: "Chief Architect", date: "May 19, 2026", width: 250 }) """ @default_width 200 @default_line_color {0.3, 0.3, 0.3} @default_name_color {0.1, 0.1, 0.1} @default_title_color {0.45, 0.45, 0.45} @default_font "Helvetica" @doc """ Render a signature block at `{x, y}`. ## Style options - `:name` — signer name (required) - `:title` — role/title below name - `:date` — optional date string - `:width` — line width (default `200`) - `:font` — font name (default `"Helvetica"`) - `:line_color` — signature line color - `:name_color` — name text color - `:title_color` — title/date text color - `:label` — label above line (e.g. "Authorized by") """ def render(doc, {x, y}, style \\ %{}) do name = Map.get(style, :name, "") title = Map.get(style, :title) date = Map.get(style, :date) label = Map.get(style, :label) width = Map.get(style, :width, @default_width) font = Map.get(style, :font, @default_font) line_color = Map.get(style, :line_color, @default_line_color) name_color = Map.get(style, :name_color, @default_name_color) title_color = Map.get(style, :title_color, @default_title_color) # Optional label above the line {doc, line_y} = if label do doc = doc |> Pdf.set_font(font, 8) |> Pdf.set_fill_color(title_color) |> Pdf.text_at({x, y}, label) {doc, y - 16} else {doc, y} end # Signature line doc = doc |> Pdf.save_state() |> Pdf.set_stroke_color(line_color) |> Pdf.set_line_width(0.8) |> Pdf.line({x, line_y}, {x + width, line_y}) |> Pdf.stroke() |> Pdf.restore_state() # Name doc = doc |> Pdf.set_font(font, 10, bold: true) |> Pdf.set_fill_color(name_color) |> Pdf.text_at({x, line_y - 14}, name) # Title doc = if title do doc |> Pdf.set_font(font, 9) |> Pdf.set_fill_color(title_color) |> Pdf.text_at({x, line_y - 26}, title) else doc end # Date (right-aligned) if date do date_w = String.length(date) * 9 * 0.52 doc |> Pdf.set_font(font, 9) |> Pdf.set_fill_color(title_color) |> Pdf.text_at({x + width - date_w, line_y - 14}, date) else doc end end end