Constants
20 hours ago
Accordion.php
20 hours ago
Alert.php
20 hours ago
AttachmentCard.php
20 hours ago
Avatar.php
20 hours ago
Badge.php
20 hours ago
BaseComponent.php
20 hours ago
Button.php
20 hours ago
ConfirmationModal.php
20 hours ago
CourseFilter.php
20 hours ago
DateFilter.php
20 hours ago
DropdownFilter.php
20 hours ago
EmptyState.php
20 hours ago
FileUploader.php
20 hours ago
InputField.php
20 hours ago
Modal.php
20 hours ago
Nav.php
20 hours ago
Pagination.php
20 hours ago
Popover.php
20 hours ago
PreviewTrigger.php
20 hours ago
Progress.php
20 hours ago
SearchFilter.php
20 hours ago
Sorting.php
20 hours ago
StarRating.php
20 hours ago
StarRatingInput.php
20 hours ago
StatusSelect.php
20 hours ago
SvgIcon.php
20 hours ago
Table.php
20 hours ago
Tabs.php
20 hours ago
Tooltip.php
20 hours ago
WPEditor.php
20 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 |