Revision 148 | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?phpdeclare(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];}}