///|
/// Vertical layout — stacks children separated by newlines.
/// Designed for use with the `<|` operator:
///
/// ```
/// col <| [
/// "header",
/// row <| ["a", " ", "b"],
/// "footer",
/// ]
/// ```
pub fn col(children : Array[String]) -> String {
join_vertical(children)
}
///|
/// Horizontal layout — places children side by side.
/// Designed for use with the `<|` operator:
///
/// ```
/// row <| [
/// stat_card("PHASE", label),
/// " ",
/// stat_card("TICKS", count),
/// ]
/// ```
pub fn row(children : Array[String]) -> String {
join_horizontal(children)
}
///|
/// Simple newline join — no width normalization or alignment.
/// Lighter than `col` when blocks are already uniform width.
pub fn lines(children : Array[String]) -> String {
@internal.join_lines(children)
}
///|
/// Identity function — returns the input string unchanged.
/// Exists for readability in DSL expressions where a bare string
/// literal would be unclear.
pub fn text(s : String) -> String {
s
}
///|
/// Produces `n` blank lines for vertical spacing inside a `col`.
/// `gap()` is equivalent to `""` — a single blank line in vertical layout.
/// `gap(n=2)` produces two blank lines (`"\n"`), and so on.
pub fn gap(n? : Int = 1) -> String {
if n <= 1 {
return ""
}
let buf = StringBuilder::new()
for i = 1; i < n; i = i + 1 {
buf.write_char('\n')
}
buf.to_string()
}
///|
/// Produces `n` spaces for horizontal spacing inside a `row`.
pub fn hgap(n? : Int = 1) -> String {
String::make(n, ' ')
}