sugarcraft/candy-layout

Constraint-based layout solver (Cassowary simplex + greedy fallback)

Maintainers

Package info

github.com/sugarcraft/candy-layout

Documentation

pkg:composer/sugarcraft/candy-layout

Transparency log

Statistics

Installs: 3 008

Dependents: 4

Suggesters: 0

Stars: 0

Open Issues: 0

dev-master 2026-07-12 15:58 UTC

This package is auto-updated.

Last update: 2026-07-13 00:24:20 UTC


README

CI codecov Packagist Version License PHP

Constraint-based layout solver for terminal grid layouts.

GreedySolver is the default and only supported solver. It is deterministic and fully implements every constraint type (Length/Min/Max/Fill/Percentage/Ratio).

CassowarySolver is deprecated — its Big-M simplex never converged (it hit the 1000-pivot cap on every call, including trivial layouts, and silently returned wrong state; its Ratio path returned 0). Rather than rewrite the simplex, CassowarySolver::solve() now emits E_USER_DEPRECATED and delegates wholly to GreedySolver. The class is retained only for backward compatibility; new code should use GreedySolver directly.

Install

composer require sugarcraft/candy-layout

Quickstart

use SugarCraft\Layout\{Constraint, Direction, GreedySolver, Region};

$solver = GreedySolver::new();
$region = Region::fromSize(100, 24);

$rects = $solver->solve($region, Direction::Horizontal, [
    Constraint::length(20),      // exactly 20 cells
    Constraint::min(10),         // at least 10, takes more if available
    Constraint::fill(1),         // fills remaining space (weight 1)
    Constraint::percentage(30),  // 30% of total
    Constraint::ratio(1, 3),     // 1/3 of remaining after fixed
    Constraint::max(50),        // ceiling — greedy but clamped
]);

Solvers

Solver Use case Status
GreedySolver Deterministic, fast, no deps; all constraint types Supported
CassowarySolver Deprecated; solve() delegates to GreedySolver + warns Deprecated

Constraint types

  • Constraint::length(int) — fixed cell count
  • Constraint::min(int) — floor, grows if slack available
  • Constraint::max(int) — ceiling, greedy, clamped
  • Constraint::fill(int $weight = 1) — proportional remainder
  • Constraint::percentage(int 0-100) — % of total
  • Constraint::ratio(int $num, int $denom) — fractional proportion

Shared foundations

candy-layout is a foundation package consumed by candy-sprinkles (step-10) and sugar-bits/candy-forms (step-14/15). The LayoutSolver interface is the only public contract. Use GreedySolver; CassowarySolver is a deprecated shim that delegates to it.

Region here is deliberately distinct from SugarCraft\Buffer\Region in candy-buffer (a leaf-package name collision that keeps candy-layout dependency-free); candy-sprinkles' RegionBridge converts between them.

References

  • Mirrors ratatui/ratatui layout constraint system
  • Based on Badros & Borning 2001 "The Cassowary Linear Arithmetic Constraint Solving Algorithm"