1*04fd306cSNickeau<?php 2*04fd306cSNickeau 3*04fd306cSNickeau 4*04fd306cSNickeaunamespace ComboStrap\TagAttribute; 5*04fd306cSNickeau 6*04fd306cSNickeau 7*04fd306cSNickeauuse ComboStrap\Bootstrap; 8*04fd306cSNickeauuse ComboStrap\ConditionalLength; 9*04fd306cSNickeauuse ComboStrap\Dimension; 10*04fd306cSNickeauuse ComboStrap\ExceptionBadArgument; 11*04fd306cSNickeauuse ComboStrap\GridTag; 12*04fd306cSNickeauuse ComboStrap\LogUtility; 13*04fd306cSNickeauuse ComboStrap\TagAttributes; 14*04fd306cSNickeau 15*04fd306cSNickeauclass Align 16*04fd306cSNickeau{ 17*04fd306cSNickeau /** 18*04fd306cSNickeau * Class to center an element 19*04fd306cSNickeau */ 20*04fd306cSNickeau public const CENTER_CLASS = "mx-auto"; 21*04fd306cSNickeau const ALIGN_ATTRIBUTE = "align"; 22*04fd306cSNickeau 23*04fd306cSNickeau /** 24*04fd306cSNickeau * Children are also known as items in HTML/CSS 25*04fd306cSNickeau * ie list items, align-center-items, ... 26*04fd306cSNickeau */ 27*04fd306cSNickeau const Y_CENTER_CHILDREN = "y-center-children"; 28*04fd306cSNickeau const Y_TOP_CHILDREN = "y-top-children"; 29*04fd306cSNickeau const X_CENTER_CHILDREN = "x-center-children"; 30*04fd306cSNickeau const DEFAULT_AXIS = self::X_AXIS; 31*04fd306cSNickeau public const X_AXIS = "x"; 32*04fd306cSNickeau public const Y_AXIS = "y"; 33*04fd306cSNickeau const CANONICAL = self::ALIGN_ATTRIBUTE; 34*04fd306cSNickeau 35*04fd306cSNickeau /** 36*04fd306cSNickeau * @param TagAttributes $attributes 37*04fd306cSNickeau */ 38*04fd306cSNickeau public static function processAlignAttributes(TagAttributes &$attributes) 39*04fd306cSNickeau { 40*04fd306cSNickeau // The class shortcut 41*04fd306cSNickeau $align = self::ALIGN_ATTRIBUTE; 42*04fd306cSNickeau $alignAttributeValues = $attributes->getValueAndRemove($align); 43*04fd306cSNickeau if ($alignAttributeValues === null || $alignAttributeValues === "") { 44*04fd306cSNickeau return; 45*04fd306cSNickeau } 46*04fd306cSNickeau 47*04fd306cSNickeau $flexAxis = null; 48*04fd306cSNickeau $blockAlign = false; 49*04fd306cSNickeau $alignValues = explode(" ", $alignAttributeValues); 50*04fd306cSNickeau foreach ($alignValues as $alignStringValue) { 51*04fd306cSNickeau 52*04fd306cSNickeau try { 53*04fd306cSNickeau $conditionalAlignValue = ConditionalLength::createFromString($alignStringValue); 54*04fd306cSNickeau } catch (ExceptionBadArgument $e) { 55*04fd306cSNickeau LogUtility::error("The align value ($alignStringValue) is not a valid conditional value and was skipped", self::CANONICAL); 56*04fd306cSNickeau continue; 57*04fd306cSNickeau } 58*04fd306cSNickeau switch ($conditionalAlignValue->getLength()) { 59*04fd306cSNickeau case "center": 60*04fd306cSNickeau case "x-center": 61*04fd306cSNickeau $blockAlign = true; 62*04fd306cSNickeau $attributes->addClassName(self::CENTER_CLASS); 63*04fd306cSNickeau /** 64*04fd306cSNickeau * Don't set: `width:fit-content` 65*04fd306cSNickeau * Setting is cool for a little block 66*04fd306cSNickeau * but it will take the max width of all children 67*04fd306cSNickeau * making the design not responsive if a table 68*04fd306cSNickeau * with `width:max-content` is a children 69*04fd306cSNickeau */ 70*04fd306cSNickeau break; 71*04fd306cSNickeau case "y-center": 72*04fd306cSNickeau $flexAxis[self::Y_AXIS] = true; 73*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 74*04fd306cSNickeau $attributes->addClassName("align-self{$breakpoint}-center"); 75*04fd306cSNickeau break; 76*04fd306cSNickeau case "right": 77*04fd306cSNickeau case "end": 78*04fd306cSNickeau $blockAlign = true; 79*04fd306cSNickeau if (Bootstrap::getBootStrapMajorVersion() == Bootstrap::BootStrapFourMajorVersion) { 80*04fd306cSNickeau $attributes->addStyleDeclarationIfNotSet("margin-left", "auto"); 81*04fd306cSNickeau } else { 82*04fd306cSNickeau $attributes->addClassName("ms-auto"); 83*04fd306cSNickeau } 84*04fd306cSNickeau $attributes->addStyleDeclarationIfNotSet(Dimension::WIDTH_KEY, "fit-content"); 85*04fd306cSNickeau break; 86*04fd306cSNickeau case "x-left-children": 87*04fd306cSNickeau case "left-children": 88*04fd306cSNickeau case "start-children": 89*04fd306cSNickeau case "x-start-children": 90*04fd306cSNickeau $flexAxis[self::X_AXIS] = true; 91*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 92*04fd306cSNickeau switch (Bootstrap::getBootStrapMajorVersion()) { 93*04fd306cSNickeau case Bootstrap::BootStrapFourMajorVersion: 94*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-left"); 95*04fd306cSNickeau break; 96*04fd306cSNickeau default: 97*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-start"); 98*04fd306cSNickeau } 99*04fd306cSNickeau break; 100*04fd306cSNickeau case "x-right-children": 101*04fd306cSNickeau case "right-children": 102*04fd306cSNickeau case "end-children": 103*04fd306cSNickeau case "x-end-children": 104*04fd306cSNickeau $flexAxis[self::X_AXIS] = true; 105*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 106*04fd306cSNickeau switch (Bootstrap::getBootStrapMajorVersion()) { 107*04fd306cSNickeau case Bootstrap::BootStrapFourMajorVersion: 108*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-right"); 109*04fd306cSNickeau break; 110*04fd306cSNickeau default: 111*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-end"); 112*04fd306cSNickeau } 113*04fd306cSNickeau break; 114*04fd306cSNickeau case "x-center-children": 115*04fd306cSNickeau case "center-children": 116*04fd306cSNickeau $flexAxis[self::X_AXIS] = true; 117*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 118*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-center"); 119*04fd306cSNickeau break; 120*04fd306cSNickeau case "x-between-children": 121*04fd306cSNickeau case "between-children": 122*04fd306cSNickeau $flexAxis[self::X_AXIS] = true; 123*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 124*04fd306cSNickeau $attributes->addClassName("justify-content{$breakpoint}-between"); 125*04fd306cSNickeau break; 126*04fd306cSNickeau case self::Y_CENTER_CHILDREN: 127*04fd306cSNickeau $flexAxis[self::Y_AXIS] = true; 128*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 129*04fd306cSNickeau $attributes->addClassName("align-items{$breakpoint}-center"); 130*04fd306cSNickeau break; 131*04fd306cSNickeau case self::Y_TOP_CHILDREN: 132*04fd306cSNickeau $flexAxis[self::Y_AXIS] = true; 133*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 134*04fd306cSNickeau $attributes->addClassName("align-items{$breakpoint}-start"); 135*04fd306cSNickeau break; 136*04fd306cSNickeau case "text-center": 137*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 138*04fd306cSNickeau $attributes->addClassName("text{$breakpoint}-center"); 139*04fd306cSNickeau break; 140*04fd306cSNickeau case "text-left": 141*04fd306cSNickeau case "text-start": 142*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 143*04fd306cSNickeau switch (Bootstrap::getBootStrapMajorVersion()) { 144*04fd306cSNickeau case Bootstrap::BootStrapFourMajorVersion: 145*04fd306cSNickeau $attributes->addClassName("text{$breakpoint}-left"); 146*04fd306cSNickeau break; 147*04fd306cSNickeau default: 148*04fd306cSNickeau $attributes->addClassName("text{$breakpoint}-start"); 149*04fd306cSNickeau } 150*04fd306cSNickeau break; 151*04fd306cSNickeau case "text-right": 152*04fd306cSNickeau case "text-end": 153*04fd306cSNickeau $breakpoint = $conditionalAlignValue->getBreakpointForBootstrapClass(); 154*04fd306cSNickeau switch (Bootstrap::getBootStrapMajorVersion()) { 155*04fd306cSNickeau case Bootstrap::BootStrapFourMajorVersion: 156*04fd306cSNickeau $attributes->addClassName("text{$breakpoint}-right"); 157*04fd306cSNickeau break; 158*04fd306cSNickeau default: 159*04fd306cSNickeau $attributes->addClassName("text{$breakpoint}-end"); 160*04fd306cSNickeau } 161*04fd306cSNickeau break; 162*04fd306cSNickeau } 163*04fd306cSNickeau 164*04fd306cSNickeau 165*04fd306cSNickeau } 166*04fd306cSNickeau 167*04fd306cSNickeau /** 168*04fd306cSNickeau * For flex element 169*04fd306cSNickeau */ 170*04fd306cSNickeau if ($flexAxis !== null) { 171*04fd306cSNickeau /** 172*04fd306cSNickeau * A bootstrap row is already a flex, no need to add it 173*04fd306cSNickeau */ 174*04fd306cSNickeau if ($attributes->getLogicalTag() !== GridTag::TAG) { 175*04fd306cSNickeau $attributes->addClassName("d-flex"); 176*04fd306cSNickeau if (!isset($flexAxis[self::Y_AXIS])) { 177*04fd306cSNickeau /** 178*04fd306cSNickeau * flex box change the line center of where the text is written 179*04fd306cSNickeau * if a flex align attribute is used in a row, a itext or any other 180*04fd306cSNickeau * component that is not a grid, we set it to center 181*04fd306cSNickeau * 182*04fd306cSNickeau * You can see this effect for instance on a badge, where the text will jump 183*04fd306cSNickeau * to the top (the flex default), without centering the flex on y 184*04fd306cSNickeau */ 185*04fd306cSNickeau $attributes->addClassName("align-items-center"); 186*04fd306cSNickeau } 187*04fd306cSNickeau } 188*04fd306cSNickeau } 189*04fd306cSNickeau 190*04fd306cSNickeau /** 191*04fd306cSNickeau * For inline element, 192*04fd306cSNickeau * center should be a block 193*04fd306cSNickeau * (svg is not a block by default for instance) 194*04fd306cSNickeau * ! 195*04fd306cSNickeau * this should not be the case for flex block such as a row 196*04fd306cSNickeau * therefore the condition 197*04fd306cSNickeau * ! 198*04fd306cSNickeau */ 199*04fd306cSNickeau if ($blockAlign === true && in_array($attributes->getLogicalTag(), TagAttributes::INLINE_LOGICAL_ELEMENTS)) { 200*04fd306cSNickeau $attributes->addClassName("d-block"); 201*04fd306cSNickeau } 202*04fd306cSNickeau 203*04fd306cSNickeau 204*04fd306cSNickeau } 205*04fd306cSNickeau} 206