Constants
23 hours ago
Accordion.php
23 hours ago
Alert.php
23 hours ago
AttachmentCard.php
23 hours ago
Avatar.php
23 hours ago
Badge.php
23 hours ago
BaseComponent.php
23 hours ago
Button.php
23 hours ago
ConfirmationModal.php
23 hours ago
CourseFilter.php
23 hours ago
DateFilter.php
23 hours ago
DropdownFilter.php
23 hours ago
EmptyState.php
23 hours ago
FileUploader.php
23 hours ago
InputField.php
23 hours ago
Modal.php
23 hours ago
Nav.php
23 hours ago
Pagination.php
23 hours ago
Popover.php
23 hours ago
PreviewTrigger.php
23 hours ago
Progress.php
23 hours ago
SearchFilter.php
23 hours ago
Sorting.php
23 hours ago
StarRating.php
23 hours ago
StarRatingInput.php
23 hours ago
StatusSelect.php
23 hours ago
SvgIcon.php
23 hours ago
Table.php
23 hours ago
Tabs.php
23 hours ago
Tooltip.php
23 hours ago
WPEditor.php
23 hours ago
Nav.php
374 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Nav Component Class. |
| 4 | * |
| 5 | * @package Tutor\Components |
| 6 | * @author Themeum |
| 7 | * @link https://themeum.com |
| 8 | * @since 4.0.0 |
| 9 | */ |
| 10 | |
| 11 | namespace Tutor\Components; |
| 12 | |
| 13 | defined( 'ABSPATH' ) || exit; |
| 14 | |
| 15 | use Tutor\Components\Constants\Color; |
| 16 | use Tutor\Components\Constants\InputType; |
| 17 | use Tutor\Components\Constants\Size; |
| 18 | use Tutor\Components\Constants\Variant; |
| 19 | use TUTOR\Icon; |
| 20 | |
| 21 | /** |
| 22 | * Class Nav |
| 23 | * |
| 24 | * Responsible for rendering the nav component. |
| 25 | * |
| 26 | * |
| 27 | * //Example Usage : |
| 28 | * |
| 29 | * ``` |
| 30 | * $items = array( |
| 31 | * array( |
| 32 | * 'type' => 'link', // 'link' or 'dropdown' |
| 33 | * 'label' => 'Wishlist', |
| 34 | * 'icon' => Icon::WISHLIST, |
| 35 | * 'url' => '#', |
| 36 | * 'active' => false, |
| 37 | * ), |
| 38 | * array( |
| 39 | * 'type' => 'dropdown', |
| 40 | * 'active' => true, |
| 41 | * 'options' => array( |
| 42 | * array( |
| 43 | * 'label' => 'Active', |
| 44 | * 'count => 4, |
| 45 | * 'icon' => Icon::PLAY_LINE, |
| 46 | * 'url' => '#', |
| 47 | * 'active' => false, |
| 48 | * ), |
| 49 | * array( |
| 50 | * 'label' => 'Enrolled', |
| 51 | * 'count => 4, |
| 52 | * 'icon' => Icon::ENROLLED, |
| 53 | * 'url' => '#', |
| 54 | * 'active' => true, |
| 55 | * ), |
| 56 | * ), |
| 57 | * ), |
| 58 | * ); |
| 59 | * |
| 60 | * echo Nav::make() |
| 61 | * ->items( array( $dropdown ) ) |
| 62 | * ->size( Size::SMALL ) |
| 63 | * ->variant( Variant::SECONDARY ) |
| 64 | * ->render(); |
| 65 | * ``` |
| 66 | * |
| 67 | * @since 4.0.0 |
| 68 | */ |
| 69 | class Nav extends BaseComponent { |
| 70 | |
| 71 | /** |
| 72 | * The nav variant. |
| 73 | * |
| 74 | * @var string |
| 75 | */ |
| 76 | protected $nav_variant = Variant::PRIMARY; |
| 77 | |
| 78 | /** |
| 79 | * The nav size. |
| 80 | * |
| 81 | * @var string |
| 82 | */ |
| 83 | protected $nav_size = Size::MEDIUM; |
| 84 | |
| 85 | /** |
| 86 | * The nav items. |
| 87 | * |
| 88 | * @var array |
| 89 | */ |
| 90 | protected $nav_items = array(); |
| 91 | |
| 92 | /** |
| 93 | * Nav attributes. |
| 94 | * |
| 95 | * @since 4.0.0 |
| 96 | * |
| 97 | * @var array |
| 98 | */ |
| 99 | protected $attributes = array(); |
| 100 | |
| 101 | /** |
| 102 | * Set the nav variant. |
| 103 | * |
| 104 | * @since 4.0.0 |
| 105 | * |
| 106 | * @param string $variant the nav variant to set. |
| 107 | * |
| 108 | * @return self |
| 109 | */ |
| 110 | public function variant( $variant = Variant::PRIMARY ): self { |
| 111 | $allowed_variants = array( Variant::PRIMARY, Variant::SECONDARY ); |
| 112 | $this->nav_variant = in_array( $variant, $allowed_variants, true ) ? $variant : Variant::PRIMARY; |
| 113 | return $this; |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * Set the nav size. |
| 118 | * |
| 119 | * @since 4.0.0 |
| 120 | * |
| 121 | * @param string $size the nav size. |
| 122 | * |
| 123 | * @return self |
| 124 | */ |
| 125 | public function size( $size = Size::MEDIUM ): self { |
| 126 | $allowed_sizes = array( Size::MEDIUM, Size::SMALL, Size::LARGE ); |
| 127 | $this->nav_size = in_array( $size, $allowed_sizes, true ) ? $size : Size::MEDIUM; |
| 128 | |
| 129 | return $this; |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Set the nav items. |
| 134 | * |
| 135 | * @since 4.0.0 |
| 136 | * |
| 137 | * @param array $items the nav items. |
| 138 | * |
| 139 | * @return self |
| 140 | */ |
| 141 | public function items( $items = array() ): self { |
| 142 | $this->nav_items = $items; |
| 143 | return $this; |
| 144 | } |
| 145 | |
| 146 | /** |
| 147 | * Get icon size for item size. |
| 148 | * |
| 149 | * @since 4.0.0 |
| 150 | * |
| 151 | * @param string $size the item size. |
| 152 | * |
| 153 | * @return integer |
| 154 | */ |
| 155 | protected function get_icon_size( $size ): int { |
| 156 | $icon_sizes = array( |
| 157 | Size::SMALL => 20, |
| 158 | Size::MEDIUM => 20, |
| 159 | Size::LARGE => 24, |
| 160 | ); |
| 161 | |
| 162 | return $icon_sizes[ $size ]; |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * Get the label of the active dropdown option. |
| 167 | * |
| 168 | * @since 4.0.0 |
| 169 | * |
| 170 | * @param array $options Array of dropdown options. |
| 171 | * |
| 172 | * @return string The label of the active option, or the first option's label * if none are active. |
| 173 | */ |
| 174 | protected function get_active_dropdown_label( array $options ): string { |
| 175 | if ( ! tutor_utils()->count( $options ) ) { |
| 176 | return ''; |
| 177 | } |
| 178 | |
| 179 | $active_option = $options[0]; |
| 180 | foreach ( $options as $option ) { |
| 181 | if ( ! empty( $option['active'] ) ) { |
| 182 | $active_option = $option; |
| 183 | break; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | $label = $active_option['label'] ?? ''; |
| 188 | if ( isset( $active_option['count'] ) ) { |
| 189 | $label .= ' (' . $active_option['count'] . ')'; |
| 190 | } |
| 191 | |
| 192 | return $label; |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * Get the icon of the active dropdown option. |
| 197 | * |
| 198 | * @since 4.0.0 |
| 199 | * |
| 200 | * @param array $options Array of dropdown options. |
| 201 | * |
| 202 | * @return string The icon of the active option, or the first option's icon if none are active. |
| 203 | */ |
| 204 | protected function get_active_dropdown_icon( array $options ): string { |
| 205 | if ( ! tutor_utils()->count( $options ) ) { |
| 206 | return ''; |
| 207 | } |
| 208 | |
| 209 | $active_option = $options[0]; |
| 210 | foreach ( $options as $option ) { |
| 211 | if ( ! empty( $option['active'] ) ) { |
| 212 | $active_option = $option; |
| 213 | break; |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | return $active_option['icon'] ?? ''; |
| 218 | } |
| 219 | |
| 220 | /** |
| 221 | * Render dropdown nav if it is selected. |
| 222 | * |
| 223 | * @since 4.0.0 |
| 224 | * |
| 225 | * @param array $item the dropdown nav item. |
| 226 | * |
| 227 | * @return string |
| 228 | */ |
| 229 | protected function render_dropdown_item( array $item ): string { |
| 230 | $dropdown = ''; |
| 231 | |
| 232 | if ( ! tutor_utils()->count( $item ) ) { |
| 233 | return ''; |
| 234 | } |
| 235 | |
| 236 | $options = $item['options'] ?? array(); |
| 237 | $active_label = $this->get_active_dropdown_label( $options ); |
| 238 | $icon_size = $this->get_icon_size( $this->nav_size ); |
| 239 | $active_item = isset( $item['active'] ) && $item['active'] ? 'active' : ''; |
| 240 | $active_icon = $this->get_active_dropdown_icon( $options ); |
| 241 | $icon = $active_icon ? SvgIcon::make()->name( $active_icon )->size( $icon_size )->get() : ''; |
| 242 | $dropdown_icon = SvgIcon::make() |
| 243 | ->name( Icon::CHEVRON_DOWN_2 ) |
| 244 | ->size( $icon_size ) |
| 245 | ->color( Color::SUBDUED ) |
| 246 | ->get(); |
| 247 | |
| 248 | $dropdown_options = ''; |
| 249 | |
| 250 | if ( count( $options ) ) { |
| 251 | foreach ( $options as $option ) { |
| 252 | $option_icon = isset( $option['icon'] ) ? SvgIcon::make()->name( $option['icon'] )->size( $icon_size )->get() : ''; |
| 253 | $is_active = isset( $option['active'] ) && $option['active'] ? 'active' : ''; |
| 254 | $label = esc_html( $option['label'] ); |
| 255 | $label = isset( $option['count'] ) ? $label . ' (' . esc_html( $option['count'] ) . ')' : $label; |
| 256 | $url = isset( $option['url'] ) ? esc_url( $option['url'] ) : '#'; |
| 257 | |
| 258 | $dropdown_options .= sprintf( |
| 259 | '<a href="%s" class="tutor-nav-dropdown-item %s"> |
| 260 | %s |
| 261 | %s |
| 262 | </a>', |
| 263 | $url, |
| 264 | $is_active, |
| 265 | $option_icon, |
| 266 | $label |
| 267 | ); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | $dropdown = sprintf( |
| 272 | '<div x-data="tutorPopover({ placement: \'bottom-start\', offset: 4 })"> |
| 273 | <button x-ref="trigger" @click="toggle()" |
| 274 | :aria-expanded="open.toString()" |
| 275 | aria-haspopup="true" |
| 276 | class="tutor-nav-item %s"> |
| 277 | %s |
| 278 | %s |
| 279 | %s |
| 280 | </button> |
| 281 | <div x-ref="content" x-show="open" x-cloak @click.outside="handleClickOutside()" class="tutor-popover tutor-nav-dropdown" x-transition.origin.top.left> |
| 282 | %s |
| 283 | </div> |
| 284 | </div>', |
| 285 | $active_item, |
| 286 | $icon, |
| 287 | esc_html( $active_label ), |
| 288 | $dropdown_icon, |
| 289 | $dropdown_options |
| 290 | ); |
| 291 | |
| 292 | return $dropdown; |
| 293 | } |
| 294 | |
| 295 | /** |
| 296 | * Render link nav item if it is selected. |
| 297 | * |
| 298 | * @since 4.0.0 |
| 299 | * |
| 300 | * @param array $item the link nav item. |
| 301 | * |
| 302 | * @return string |
| 303 | */ |
| 304 | protected function render_link_item( array $item ): string { |
| 305 | $dropdown = ''; |
| 306 | |
| 307 | if ( ! tutor_utils()->count( $item ) ) { |
| 308 | return ''; |
| 309 | } |
| 310 | |
| 311 | $active_item = isset( $item['active'] ) && $item['active'] ? 'active' : ''; |
| 312 | $url = isset( $item['url'] ) ? esc_url( $item['url'] ) : '#'; |
| 313 | $icon_size = $this->get_icon_size( $this->nav_size ); |
| 314 | $label = esc_html( $item['label'] ?? '' ); |
| 315 | $label = isset( $item['count'] ) ? $label . ' (' . esc_html( $item['count'] ) . ')' : $label; |
| 316 | $icon = isset( $item['icon'] ) ? SvgIcon::make()->name( $item['icon'] )->size( $icon_size )->get() : ''; |
| 317 | |
| 318 | $dropdown = sprintf( |
| 319 | '<a href="%s" class="tutor-nav-item %s"> |
| 320 | %s |
| 321 | %s |
| 322 | </a>', |
| 323 | $url, |
| 324 | $active_item, |
| 325 | $icon, |
| 326 | $label |
| 327 | ); |
| 328 | |
| 329 | return $dropdown; |
| 330 | } |
| 331 | |
| 332 | /** |
| 333 | * Get the HTML nav component. |
| 334 | * |
| 335 | * @since 4.0.0 |
| 336 | * |
| 337 | * @return string |
| 338 | */ |
| 339 | public function get(): string { |
| 340 | if ( ! count( $this->nav_items ) ) { |
| 341 | return ''; |
| 342 | } |
| 343 | |
| 344 | $nav_items = ''; |
| 345 | |
| 346 | foreach ( $this->nav_items as $nav_item ) { |
| 347 | if ( isset( $nav_item['type'] ) && InputType::DROPDOWN === $nav_item['type'] ) { |
| 348 | $nav_items .= $this->render_dropdown_item( $nav_item ); |
| 349 | } else { |
| 350 | $nav_items .= $this->render_link_item( $nav_item ); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | $classes = sprintf( |
| 355 | 'tutor-nav tutor-nav-%s tutor-nav-%s', |
| 356 | $this->nav_size, |
| 357 | $this->nav_variant, |
| 358 | ); |
| 359 | |
| 360 | // Merge with any custom class attribute. |
| 361 | $this->attributes['class'] = trim( "{$classes} " . ( $this->attributes['class'] ?? '' ) ); |
| 362 | |
| 363 | $attributes = $this->get_attributes_string(); |
| 364 | |
| 365 | return sprintf( |
| 366 | '<div %s> |
| 367 | %s |
| 368 | </div>', |
| 369 | $attributes, |
| 370 | $nav_items |
| 371 | ); |
| 372 | } |
| 373 | } |
| 374 |