Co-authored-by: Martin Slachta <martin.slachta@outlook.com> Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Reservair\Layout;
|
||||
|
||||
/**
|
||||
* Fluent builder for multi-column admin page layouts.
|
||||
*
|
||||
* Lets a page declare the shape it wants (e.g. a two-column split) without
|
||||
* committing to any markup or styling. Each column's content is supplied as a
|
||||
* callable that echoes — inline HTML and <script> blocks work as usual.
|
||||
*
|
||||
* Usage:
|
||||
* RsvColumnLayout::split('1:2')
|
||||
* ->column(function () { ?>
|
||||
* <h2>Add timetable</h2>
|
||||
* ...
|
||||
* <?php })
|
||||
* ->column(function () { ?>
|
||||
* <div id="availability_table"></div>
|
||||
* ...
|
||||
* <?php })
|
||||
* ->output();
|
||||
*/
|
||||
class RsvColumnLayout
|
||||
{
|
||||
/** @var list<callable():void> Column content, in left-to-right order. */
|
||||
private array $columns = [];
|
||||
|
||||
/** @var list<int> Relative column weights, parsed from the ratio. */
|
||||
private array $weights;
|
||||
|
||||
private function __construct(string $ratio)
|
||||
{
|
||||
$this->weights = array_map('intval', explode(':', $ratio));
|
||||
}
|
||||
|
||||
/**
|
||||
* Side-by-side columns that stack on narrow screens.
|
||||
*
|
||||
* @param string $ratio Relative column widths, e.g. '1:1', '1:2'.
|
||||
*/
|
||||
public static function split(string $ratio = '1:1'): static
|
||||
{
|
||||
return new static($ratio);
|
||||
}
|
||||
|
||||
/** Adds the next column. $render echoes the column's content. */
|
||||
public function column(callable $render): static
|
||||
{
|
||||
$this->columns[] = $render;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render(): string
|
||||
{
|
||||
$cols = '';
|
||||
foreach ($this->columns as $i => $render) {
|
||||
$grow = $this->weights[$i] ?? end($this->weights) ?: 1;
|
||||
$cols .= '<div class="rsv-col" style="--rsv-col-grow:' . (int) $grow . '">'
|
||||
. $this->capture($render)
|
||||
. '</div>';
|
||||
}
|
||||
return '<div class="rsv-cols">' . $cols . '</div>';
|
||||
}
|
||||
|
||||
public function output(): void
|
||||
{
|
||||
echo $this->render();
|
||||
}
|
||||
|
||||
/** Runs an echoing callable and returns what it printed. */
|
||||
private function capture(callable $render): string
|
||||
{
|
||||
ob_start();
|
||||
$render();
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user