sugarcraft / candy-layout
Constraint-based layout solver (Cassowary simplex + greedy fallback)
Requires
- php: ^8.3
Requires (Dev)
- phpunit/phpunit: ^10.5
This package is auto-updated.
Last update: 2026-07-13 00:24:20 UTC
README
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 countConstraint::min(int)— floor, grows if slack availableConstraint::max(int)— ceiling, greedy, clampedConstraint::fill(int $weight = 1)— proportional remainderConstraint::percentage(int 0-100)— % of totalConstraint::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"