xref: /template/strap/ComboStrap/TagAttribute/Align.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
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