Skip to main content

API reference — layout

All types live in core.term.layout. See the layout concept page for guided usage.

Rect​

public type Rect is { x: Int, y: Int, width: Int, height: Int };

Rect.new(x, y, w, h) -> Rect
fn area(&self) -> Int // width * height
fn left(&self) -> Int // x
fn top(&self) -> Int // y
fn right(&self) -> Int // x + width
fn bottom(&self) -> Int // y + height
fn is_empty(&self) -> Bool
fn contains(&self, x: Int, y: Int) -> Bool
fn inner(&self, m: Margin) -> Rect
fn intersection(&self, other: &Rect) -> Rect
fn union(&self, other: &Rect) -> Rect
fn centered(&self, width: Int, height: Int) -> Rect
fn clamp_position(&self, x: Int, y: Int) -> (Int, Int)
// Both split at ONE position and answer the PAIR:
fn split_horizontal(&self, at: Int) -> (Rect, Rect)
fn split_vertical(&self, at: Int) -> (Rect, Rect)

Margin​

public type Margin is { top: Int, right: Int, bottom: Int, left: Int };

// There is no `Margin.new`, `.all` or `.custom`. Four constructors,
// and `symmetric` takes HORIZONTAL first.
Margin.uniform(n: Int) -> Margin
Margin.horizontal(n: Int) -> Margin
Margin.vertical(n: Int) -> Margin
Margin.symmetric(h: Int, v: Int) -> Margin
Margin.ZERO // the const
fn total_horizontal(&self) -> Int
fn total_vertical(&self) -> Int

LayoutConstraint​

Use LayoutConstraint for terminal layout. core.database.Constraint is a separate type.

public type LayoutConstraint is
| Length(Int)
| Min(Int)
| Max(Int)
| Percentage(Int)
| Ratio(Int, Int)
| Fill(Int);

public type Direction is Horizontal | Vertical;

public type Flex is Start | Center | End | SpaceBetween | SpaceAround;

// From core/term/layout/constraint.vr. The type is `TermLayout`, not
// `Layout` — `Layout` is taken twice elsewhere in the stdlib
// (`core/math/tensor.vr` aliases it to `TensorLayout`, and
// `core/mem/allocator.vr` declares its own), and a bare `Layout` here
// resolves to one of those.
//
// Direction is chosen by the CONSTRUCTOR, so there is no
// `.direction(...)` builder.
public type TermLayout is {
direction: Direction, constraints: List<LayoutConstraint>,
margin: Margin, flex: Flex, spacing: Int,
};

TermLayout.horizontal() -> TermLayout
TermLayout.vertical() -> TermLayout
.constraints(cs: List<LayoutConstraint>) -> TermLayout
.margin(m: Margin) -> TermLayout
.flex(f: Flex) -> TermLayout
.spacing(n: Int) -> TermLayout
.split(&self, area: Rect) -> List<Rect>

Flex layout​

public type FlexLayout is {
direction: FlexDirection,
wrap: FlexWrap,
justify_content: JustifyContent,
align_items: AlignItems,
align_content: AlignContent,
gap: Int,
};

public type FlexDirection is Row | RowReverse | Column | ColumnReverse;
public type FlexWrap is NoWrap | Wrap | WrapReverse;

public type JustifyContent is
| FlexStart | FlexEnd | Center
| SpaceBetween | SpaceAround | SpaceEvenly;

public type AlignItems is Stretch | FlexStart | FlexEnd | Center | Baseline;
public type AlignContent is FlexStart | FlexEnd | Center | Stretch | SpaceBetween | SpaceAround;

public type FlexBasis is Auto | Fixed(Int) | Percentage(Int);

public type FlexItem is {
basis: FlexBasis,
grow: Float,
shrink: Float,
min_size: Maybe<Int>,
max_size: Maybe<Int>,
align_self: Maybe<AlignItems>,
};
FlexLayout.row()
FlexLayout.column()
.wrap(w)
.justify(j)
.align_items(a)
.align_content(ac) .gap(n)
.compute(container: Rect, items: &List<FlexItem>) -> List<Rect>
FlexItem.new()
.grow(f: Float)
.shrink(f: Float)
.fixed(n: Int)
.percentage(p: Int) .min(n: Int)
.max(n: Int)
.align(a: AlignItems)

Grid layout​

public type GridTrack is
| Fixed(Int)
| Fr(Float)
| MinMax(Int, Int)
| Auto;

public type GridLayout is { ... };

GridLayout.new(columns: List<GridTrack>, rows: List<GridTrack>)
.gap(n: Int) // or .column_gap(n) / .row_gap(n)
.compute(area: &Rect) -> List<List<Rect>> // [row][column]

Shortcuts​

mount core.term.layout.shortcuts.*;

fn header_body_footer(area: Rect, header_h: Int, footer_h: Int) -> (Rect, Rect, Rect);
fn sidebar_main(area: Rect, sidebar_width: Int) -> (Rect, Rect);
fn centered(area: Rect, width: Int, height: Int) -> Rect;
fn equal_columns(area: Rect, n: Int) -> List<Rect>;
fn equal_rows(area: Rect, n: Int) -> List<Rect>;
fn percentage_split(area: Rect, percentages: &List<Int>) -> List<Rect>;
fn percentage_rows(area: Rect, percentages: &List<Int>) -> List<Rect>;

Responsive​

Breakpoint is a RECORD carrying its own threshold and name, not a four-variant sum. The four standard ones are module CONSTANTS, so a project can define its own beside them.

public type Breakpoint is { min_width: Int, name: Text };

public const MOBILE: Breakpoint = Breakpoint { min_width: 0, name: "mobile" };
public const TABLET: Breakpoint = Breakpoint { min_width: 80, name: "tablet" };
public const DESKTOP: Breakpoint = Breakpoint { min_width: 120, name: "desktop" };
public const WIDE: Breakpoint = Breakpoint { min_width: 160, name: "wide" };

public fn current_breakpoint(width: Int) -> Breakpoint;

Thresholds: mobile < 80 ≤ tablet < 120 ≤ desktop < 160 ≤ wide — the last boundary is 160, and current_breakpoint compares against min_width from the widest down.