Bootstrap->progressTimeline([ * 'selected' => 1, * 'steps' => [ * [ * 'text' => __('Step 1'), * 'icon' => 'star', * 'title' => __('Title'), * ], * [ * 'text' => __('Step 3'), * 'icon' => 'exchange-alt', * ] * ], * ]); */ class BootstrapProgressTimeline extends BootstrapGeneric { private $defaultOptions = [ 'steps' => [], 'selected' => 0, 'variant' => 'primary', 'variantInactive' => 'secondary', ]; function __construct($options, $btHelper) { $this->allowedOptionValues = [ 'variant' => BootstrapGeneric::$variants, 'variantInactive' => BootstrapGeneric::$variants, ]; $this->processOptions($options); $this->btHelper = $btHelper; } private function processOptions($options) { $this->options = array_merge($this->defaultOptions, $options); $this->checkOptionValidity(); } public function progressTimeline() { return $this->genProgressTimeline(); } private function getStepIcon($step, $i, $nodeActive, $lineActive) { $icon = $this->node('b', [ 'class' => [ !empty($step['icon']) ? h($this->btHelper->FontAwesome->getClass($step['icon'])) : '', $this->getTextClassForVariant($this->options['variant']) ], ], empty($step['icon']) ? h($i + 1) : ''); $containerDefaultClass = [ 'd-flex', 'align-items-center', 'justify-content-center', 'rounded-circle', ]; $containerDefaultClass[] = $nodeActive ? "bg-{$this->options['variant']}" : "bg-{$this->options['variantInactive']}"; $iconContainer = $this->node('span', [ 'class' => $containerDefaultClass, 'style' => 'width:50px; height:50px' ], $icon); $li = $this->node('li', [ 'class' => [ 'd-flex', 'flex-column', $nodeActive ? 'progress-active' : 'progress-inactive', ], ], $iconContainer); $html = $li . $this->getHorizontalLine($i, $nodeActive, $lineActive); return $html; } private function getHorizontalLine($i, $nodeActive, $lineActive) { $stepCount = count($this->options['steps']); if ($i == $stepCount - 1) { return ''; } $progressBar = (new BootstrapProgress([ 'label' => false, 'value' => $nodeActive ? ($lineActive ? 100 : 50) : 0, 'height' => '2px', 'variant' => $this->options['variant'] ]))->progress(); $line = $this->node('span', [ 'class' => [ 'progress-line', 'flex-grow-1', 'align-self-center', $lineActive ? "bg-{$this->options['variant']}" : '' ], ], $progressBar); return $line; } private function getStepText($step, $isActive) { return $this->node('li', [ 'class' => [ 'text-center', 'fw-bold', $isActive ? 'progress-active' : 'progress-inactive', ], ], h($step['text'] ?? '')); } private function genProgressTimeline() { $iconLis = ''; $textLis = ''; foreach ($this->options['steps'] as $i => $step) { $nodeActive = $i <= $this->options['selected']; $lineActive = $i < $this->options['selected']; $iconLis .= $this->getStepIcon($step, $i, $nodeActive, $lineActive); $textLis .= $this->getStepText($step, $nodeActive); } $ulIcons = $this->node('ul', [ 'class' => [ 'd-flex', 'justify-content-around', ], ], $iconLis); $ulText = $this->node('ul', [ 'class' => [ 'd-flex', 'justify-content-between', ], ], $textLis); $html = $this->node('div', [ 'class' => ['progress-timeline', 'mw-75', 'mx-auto'] ], $ulIcons . $ulText); return $html; } }