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