<?php
declare(strict_types=1);
namespace Termwind\Html;
use Termwind\Components\Element;
use Termwind\Termwind;
use Termwind\ValueObjects\Styles;
/**
* @internal
*/
final class InheritStyles
{
/**
* Applies styles from parent element to child elements.
*
* @param array<int, Element|string> $elements
* @return array<int, Element|string>
*/
public function __invoke(array $elements, Styles $styles): array
{
$elements = array_values($elements);
foreach ($elements as &$element) {
if (is_string($element)) {
$element = Termwind::raw($element);
}
$element->inheritFromStyles($styles);
}
/** @var Element[] $elements */
if (($styles->getProperties()['styles']['display'] ?? 'inline') === 'flex') {
$elements = $this->applyFlex($elements);
}
return match ($styles->getProperties()['styles']['justifyContent'] ?? false) {
'between' => $this->applyJustifyBetween($elements),
'evenly' => $this->applyJustifyEvenly($elements),
'around' => $this->applyJustifyAround($elements),
'center' => $this->applyJustifyCenter($elements),
default => $elements,
};
}
/**
* Applies flex-1 to child elements with the class.
*
* @param array<int, Element> $elements
* @return array<int, Element>
*/
private function applyFlex(array $elements): array
{
[$totalWidth, $parentWidth] = $this->getWidthFromElements($elements);
$width = max(0, array_reduce($elements, function ($carry, $element) {
return $carry += $element->hasStyle('flex-1') ? $element->getInnerWidth() : 0;
}, $parentWidth - $totalWidth));
$flexed = array_values(array_filter(
$elements, fn ($element) => $element->hasStyle('flex-1')
));
foreach ($flexed as $index => &$element) {
if ($width === 0 && ! ($element->getProperties()['styles']['contentRepeat'] ?? false)) {
continue;
}
$float = $width / count($flexed);
$elementWidth = floor($float);
if ($index === count($flexed) - 1) {
$elementWidth += ($float - floor($float)) * count($flexed);
}
$element->addStyle("w-{$elementWidth}");
}
return $elements;
}
/**
* Applies the space between the elements.
*
* @param array<int, Element> $elements
* @return array<int, Element|string>
*/
private function applyJustifyBetween(array $elements): array
{
if (count($elements) <= 1) {
return $elements;
}
[$totalWidth, $parentWidth] = $this->getWidthFromElements($elements);
$space = ($parentWidth - $totalWidth) / (count($elements) - 1);
if ($space < 1) {
return $elements;
}
$arr = [];
foreach ($elements as $index => &$element) {
if ($index !== 0) {
// Since there is no float pixel, on the last one it should round up...
$length = $index === count($elements) - 1 ? ceil($space) : floor($space);
$arr[] = str_repeat(' ', (int) $length);
}
$arr[] = $element;
}
return $arr;
}
/**
* Applies the space between and around the elements.
*
* @param array<int, Element> $elements
* @return array<int, Element|string>
*/
private function applyJustifyEvenly(array $elements): array
{
[$totalWidth, $parentWidth] = $this->getWidthFromElements($elements);
$space = ($parentWidth - $totalWidth) / (count($elements) + 1);
if ($space < 1) {
return $elements;
}
$arr = [];
foreach ($elements as &$element) {
$arr[] = str_repeat(' ', (int) floor($space));
$arr[] = $element;
}
$decimals = ceil(($space - floor($space)) * (count($elements) + 1));
$arr[] = str_repeat(' ', (int) (floor($space) + $decimals));
return $arr;
}
/**
* Applies the space around the elements.
*
* @param array<int, Element> $elements
* @return array<int, Element|string>
*/
private function applyJustifyAround(array $elements): array
{
if (count($elements) === 0) {
return $elements;
}
[$totalWidth, $parentWidth] = $this->getWidthFromElements($elements);
$space = ($parentWidth - $totalWidth) / count($elements);
if ($space < 1) {
return $elements;
}
$contentSize = $totalWidth;
$arr = [];
foreach ($elements as $index => &$element) {
if ($index !== 0) {
$arr[] = str_repeat(' ', (int) ceil($space));
$contentSize += ceil($space);
}
$arr[] = $element;
}
return [
str_repeat(' ', (int) floor(($parentWidth - $contentSize) / 2)),
...$arr,
str_repeat(' ', (int) ceil(($parentWidth - $contentSize) / 2)),
];
}
/**
* Applies the space on before first element and after last element.
*
* @param array<int, Element> $elements
* @return array<int, Element|string>
*/
private function applyJustifyCenter(array $elements): array
{
[$totalWidth, $parentWidth] = $this->getWidthFromElements($elements);
$space = $parentWidth - $totalWidth;
if ($space < 1) {
return $elements;
}
return [
str_repeat(' ', (int) floor($space / 2)),
...$elements,
str_repeat(' ', (int) ceil($space / 2)),
];
}
/**
* Gets the total width for the elements and their parent width.
*
* @param array<int, Element> $elements
* @return int[]
*/
private function getWidthFromElements(array $elements)
{
$totalWidth = (int) array_reduce($elements, fn ($carry, $element) => $carry += $element->getLength(), 0);
$parentWidth = Styles::getParentWidth($elements[0]->getProperties()['parentStyles'] ?? []);
return [$totalWidth, $parentWidth];
}
}
If you encounter any issues or need assistance, please reach out to our dedicated developer support team Contact Us
Thank you for choosing Kueue Pay Payment Gateway Solutions! We look forward to seeing your integration thrive and provide a seamless payment experience for your valued customers.