// Typst template for member export (PDF) // Expected sys.inputs.elixir_data: // { // "columns": [{"key": "...", "kind": "...", "label": "..."}, ...], // "rows": [["cell1", "cell2", ...], ...], // "meta": {"generated_at": "...", "member_count": 123} // } #set page( paper: "a4", flipped: true, margin: (top: 1.2cm, bottom: 1.2cm, left: 1.0cm, right: 1.0cm) ) #set text(size: 9pt, hyphenate: true) #set heading(numbering: none) // Enable text wrapping in table cells #show table.cell: it => box(width: 100%)[#it] #let data = sys.inputs.elixir_data #let columns = data.at("columns", default: ()) #let rows = data.at("rows", default: ()) #let meta = data.at("meta", default: (generated_at: "", member_count: rows.len())) #let title = data.at("title", default: "Member Export") #let created_at_label = data.at("created_at_label", default: "Created at:") #let member_count_label = data.at("member_count_label", default: "Member count:") // Title #align(center)[ #text(size: 14pt, weight: "bold")[#title] ] #v(0.4cm) // Export metadata #set text(size: 8pt, fill: black) #grid( columns: (1fr, 1fr), gutter: 1cm, [*#created_at_label* #meta.at("generated_at", default: "")], [*#member_count_label* #meta.at("member_count", default: rows.len())], ) #v(0.6cm) // ---- Horizontal paging config ---- #let fixed_count = calc.min(2, columns.len()) #let max_dynamic_cols = 5 #let fixed_col_widths = (32mm, 32mm) #let fixed_cols = columns.slice(0, fixed_count) #let dynamic_cols = columns.slice(fixed_count, columns.len()) #let dynamic_chunks = dynamic_cols.chunks(max_dynamic_cols) #let render_chunk(chunk_index, dyn_cols_chunk) = [ #let dyn_count = dyn_cols_chunk.len() #let start = fixed_count + chunk_index * max_dynamic_cols #let page_cols = fixed_cols + dyn_cols_chunk #let headers = page_cols.map(c => c.at("label", default: "")) // widths: first two columns fixed (32mm, 42mm), rest distributed as 1fr #let widths = ( if fixed_count >= 1 { fixed_col_widths.at(0) } else { 1fr }, if fixed_count >= 2 { fixed_col_widths.at(1) } else { 1fr }, ..((1fr,) * dyn_count) ) #let header_cells = headers.map(h => text(weight: "bold", size: 9pt)[#h]) // Body cells (row-major), nur die Spalten dieses Chunks #let body_cells = ( rows .map(row => row.slice(0, fixed_count) + row.slice(start, start + dyn_count)) .map(cells => cells.map(cell => text(size: 8.5pt)[#cell])) .flatten() ) #table( columns: widths, table.header(..header_cells), ..body_cells, ) ] // ---- Output ---- #if dynamic_cols.len() == 0 { render_chunk(0, ()) } else { for (i, chunk) in dynamic_chunks.enumerate() { render_chunk(i, chunk) if i < dynamic_chunks.len() - 1 { pagebreak() } } }