Constants
22 hours ago
Accordion.php
22 hours ago
Alert.php
22 hours ago
AttachmentCard.php
22 hours ago
Avatar.php
22 hours ago
Badge.php
22 hours ago
BaseComponent.php
22 hours ago
Button.php
22 hours ago
ConfirmationModal.php
22 hours ago
CourseFilter.php
22 hours ago
DateFilter.php
22 hours ago
DropdownFilter.php
22 hours ago
EmptyState.php
22 hours ago
FileUploader.php
22 hours ago
InputField.php
22 hours ago
Modal.php
22 hours ago
Nav.php
22 hours ago
Pagination.php
22 hours ago
Popover.php
22 hours ago
PreviewTrigger.php
22 hours ago
Progress.php
22 hours ago
SearchFilter.php
22 hours ago
Sorting.php
22 hours ago
StarRating.php
22 hours ago
StarRatingInput.php
22 hours ago
StatusSelect.php
22 hours ago
SvgIcon.php
22 hours ago
Table.php
22 hours ago
Tabs.php
22 hours ago
Tooltip.php
22 hours ago
WPEditor.php
22 hours ago
Progress.php
424 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Tutor Component: Progress |
| 4 | * |
| 5 | * Provides a fluent builder for rendering progress bars and progress circles |
| 6 | * with different states and animations. |
| 7 | * |
| 8 | * @package Tutor\Components |
| 9 | * @author Themeum |
| 10 | * @link https://themeum.com |
| 11 | * @since 4.0.0 |
| 12 | */ |
| 13 | |
| 14 | namespace Tutor\Components; |
| 15 | |
| 16 | defined( 'ABSPATH' ) || exit; |
| 17 | |
| 18 | use Tutor\Components\Constants\Size; |
| 19 | use Tutor\Components\Constants\Variant; |
| 20 | |
| 21 | /** |
| 22 | * Progress Component Class. |
| 23 | * |
| 24 | * Example usage: |
| 25 | * ``` |
| 26 | * // Progress bar |
| 27 | * Progress::make() |
| 28 | * ->type( 'bar' ) |
| 29 | * ->value( 75 ) |
| 30 | * ->animated() |
| 31 | * ->render(); |
| 32 | * |
| 33 | * // Progress circle |
| 34 | * Progress::make() |
| 35 | * ->type( 'circle' ) |
| 36 | * ->value( 75 ) |
| 37 | * ->render(); |
| 38 | * |
| 39 | * ``` |
| 40 | * |
| 41 | * @since 4.0.0 |
| 42 | */ |
| 43 | class Progress extends BaseComponent { |
| 44 | |
| 45 | /** |
| 46 | * Progress type (bar|circle). |
| 47 | * |
| 48 | * @since 4.0.0 |
| 49 | * @var string |
| 50 | */ |
| 51 | protected $type = 'bar'; |
| 52 | |
| 53 | /** |
| 54 | * Progress value (0-100). |
| 55 | * |
| 56 | * @since 4.0.0 |
| 57 | * @var int |
| 58 | */ |
| 59 | protected $value = 0; |
| 60 | |
| 61 | /** |
| 62 | * Whether progress bar is animated. |
| 63 | * |
| 64 | * @since 4.0.0 |
| 65 | * @var bool |
| 66 | */ |
| 67 | protected $animated = true; |
| 68 | |
| 69 | /** |
| 70 | * Progress circle state (progress|complete). |
| 71 | * Only applicable for circle type. |
| 72 | * |
| 73 | * @since 4.0.0 |
| 74 | * @var string |
| 75 | */ |
| 76 | protected $state = 'progress'; |
| 77 | |
| 78 | /** |
| 79 | * Progress size (x-small|small|medium|large). |
| 80 | * |
| 81 | * @since 4.0.0 |
| 82 | * @var string |
| 83 | */ |
| 84 | protected $size = Size::SMALL; |
| 85 | |
| 86 | /** |
| 87 | * Progress variant style (brand|warning, etc). |
| 88 | * |
| 89 | * @since 4.0.0 |
| 90 | * |
| 91 | * @see Variant constants |
| 92 | * |
| 93 | * @var string |
| 94 | */ |
| 95 | protected $variant = ''; |
| 96 | |
| 97 | /** |
| 98 | * Background color. |
| 99 | * |
| 100 | * @since 4.0.0 |
| 101 | * @var string |
| 102 | */ |
| 103 | protected $background = 'none'; |
| 104 | |
| 105 | /** |
| 106 | * Stroke color (background circle). |
| 107 | * |
| 108 | * @since 4.0.0 |
| 109 | * @var string |
| 110 | */ |
| 111 | protected $stroke_color = 'var(--tutor-actions-gray-secondary)'; |
| 112 | |
| 113 | /** |
| 114 | * Progress stroke color (progress arc). |
| 115 | * |
| 116 | * @since 4.0.0 |
| 117 | * @var string |
| 118 | */ |
| 119 | protected $progress_stroke_color = 'var(--tutor-actions-brand-primary)'; |
| 120 | |
| 121 | /** |
| 122 | * Whether to show label. |
| 123 | * |
| 124 | * @since 4.0.0 |
| 125 | * @var bool |
| 126 | */ |
| 127 | protected $show_label = true; |
| 128 | |
| 129 | /** |
| 130 | * Custom label text. |
| 131 | * |
| 132 | * @since 4.0.0 |
| 133 | * @var string |
| 134 | */ |
| 135 | protected $label = ''; |
| 136 | |
| 137 | /** |
| 138 | * Animation duration in milliseconds. |
| 139 | * |
| 140 | * @since 4.0.0 |
| 141 | * @var int |
| 142 | */ |
| 143 | protected $duration = 1000; |
| 144 | |
| 145 | /** |
| 146 | * Set progress type. |
| 147 | * |
| 148 | * @since 4.0.0 |
| 149 | * |
| 150 | * @param string $type Progress type (bar|circle). |
| 151 | * @return $this |
| 152 | */ |
| 153 | public function type( $type ) { |
| 154 | $allowed = array( 'bar', 'circle' ); |
| 155 | if ( in_array( $type, $allowed, true ) ) { |
| 156 | $this->type = $type; |
| 157 | } |
| 158 | return $this; |
| 159 | } |
| 160 | |
| 161 | /** |
| 162 | * Set progress value (0-100). |
| 163 | * |
| 164 | * @since 4.0.0 |
| 165 | * |
| 166 | * @param int $value Progress value. |
| 167 | * @return $this |
| 168 | */ |
| 169 | public function value( $value ) { |
| 170 | $this->value = max( 0, min( 100, (int) $value ) ); |
| 171 | return $this; |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * Enable animated progress bar. |
| 176 | * |
| 177 | * @since 4.0.0 |
| 178 | * |
| 179 | * @param bool $animated Whether to animate the progress bar. |
| 180 | * @return $this |
| 181 | */ |
| 182 | public function animated( $animated = true ) { |
| 183 | $this->animated = (bool) $animated; |
| 184 | return $this; |
| 185 | } |
| 186 | |
| 187 | /** |
| 188 | * Set progress size. |
| 189 | * |
| 190 | * @since 4.0.0 |
| 191 | * |
| 192 | * @param string $size Progress size (x-small|small|medium|large). |
| 193 | * @return $this |
| 194 | */ |
| 195 | public function size( $size ) { |
| 196 | $allowed = array( Size::X_SMALL, Size::SMALL, Size::MEDIUM, Size::LARGE ); |
| 197 | if ( in_array( $size, $allowed, true ) ) { |
| 198 | $this->size = $size; |
| 199 | } |
| 200 | return $this; |
| 201 | } |
| 202 | |
| 203 | /** |
| 204 | * Set progress variant style. |
| 205 | * |
| 206 | * @since 4.0.0 |
| 207 | * |
| 208 | * @param string $variant Progress variant (brand|warning, etc). |
| 209 | * @return $this |
| 210 | */ |
| 211 | public function variant( $variant ) { |
| 212 | $this->variant = sanitize_html_class( $variant ); |
| 213 | return $this; |
| 214 | } |
| 215 | |
| 216 | /** |
| 217 | * Set progress state. |
| 218 | * |
| 219 | * @since 4.0.0 |
| 220 | * |
| 221 | * @param string $state Progress state (progress|complete|locked). |
| 222 | * @return $this |
| 223 | */ |
| 224 | public function state( $state ) { |
| 225 | $allowed = array( 'progress', 'complete', 'locked' ); |
| 226 | if ( in_array( $state, $allowed, true ) ) { |
| 227 | $this->state = $state; |
| 228 | } |
| 229 | return $this; |
| 230 | } |
| 231 | |
| 232 | /** |
| 233 | * Set progress as complete. |
| 234 | * |
| 235 | * @since 4.0.0 |
| 236 | * @return $this |
| 237 | */ |
| 238 | public function complete() { |
| 239 | return $this->state( 'complete' ); |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * Set progress as locked. |
| 244 | * |
| 245 | * @since 4.0.0 |
| 246 | * @return $this |
| 247 | */ |
| 248 | public function locked() { |
| 249 | return $this->state( 'locked' ); |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * Set background color. |
| 254 | * |
| 255 | * @since 4.0.0 |
| 256 | * |
| 257 | * @param string $background Background color. |
| 258 | * @return $this |
| 259 | */ |
| 260 | public function background( $background ) { |
| 261 | $this->background = $background; |
| 262 | return $this; |
| 263 | } |
| 264 | |
| 265 | /** |
| 266 | * Set stroke color (background circle). |
| 267 | * |
| 268 | * @since 4.0.0 |
| 269 | * |
| 270 | * @param string $stroke_color Stroke color. |
| 271 | * @return $this |
| 272 | */ |
| 273 | public function stroke_color( $stroke_color ) { |
| 274 | $this->stroke_color = $stroke_color; |
| 275 | return $this; |
| 276 | } |
| 277 | |
| 278 | /** |
| 279 | * Set progress stroke color (progress arc). |
| 280 | * |
| 281 | * @since 4.0.0 |
| 282 | * |
| 283 | * @param string $progress_stroke_color Progress stroke color. |
| 284 | * @return $this |
| 285 | */ |
| 286 | public function progress_stroke_color( $progress_stroke_color ) { |
| 287 | $this->progress_stroke_color = $progress_stroke_color; |
| 288 | return $this; |
| 289 | } |
| 290 | |
| 291 | /** |
| 292 | * Set whether to show label. |
| 293 | * |
| 294 | * @since 4.0.0 |
| 295 | * |
| 296 | * @param bool $show_label Whether to show label. |
| 297 | * @return $this |
| 298 | */ |
| 299 | public function show_label( $show_label = true ) { |
| 300 | $this->show_label = (bool) $show_label; |
| 301 | return $this; |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * Set custom label text. |
| 306 | * |
| 307 | * @since 4.0.0 |
| 308 | * |
| 309 | * @param string $label Custom label text. |
| 310 | * @return $this |
| 311 | */ |
| 312 | public function label( $label ) { |
| 313 | $this->label = $label; |
| 314 | return $this; |
| 315 | } |
| 316 | |
| 317 | /** |
| 318 | * Set animation duration. |
| 319 | * |
| 320 | * @since 4.0.0 |
| 321 | * |
| 322 | * @param int $duration Animation duration in milliseconds. |
| 323 | * @return $this |
| 324 | */ |
| 325 | public function duration( $duration ) { |
| 326 | $this->duration = (int) $duration; |
| 327 | return $this; |
| 328 | } |
| 329 | |
| 330 | /** |
| 331 | * Render progress bar HTML. |
| 332 | * |
| 333 | * @since 4.0.0 |
| 334 | * |
| 335 | * @return string HTML output. |
| 336 | */ |
| 337 | protected function render_bar() { |
| 338 | $classes = 'tutor-progress-bar'; |
| 339 | |
| 340 | if ( ! empty( $this->variant ) ) { |
| 341 | $classes .= " tutor-progress-bar-{$this->variant}"; |
| 342 | } |
| 343 | |
| 344 | // Add animated attribute if enabled. |
| 345 | if ( $this->animated ) { |
| 346 | $this->attributes['data-tutor-animated'] = ''; |
| 347 | } |
| 348 | |
| 349 | // Merge classes. |
| 350 | $this->attributes['class'] = trim( "{$classes} " . ( $this->attributes['class'] ?? '' ) ); |
| 351 | |
| 352 | $attributes = $this->get_attributes_string(); |
| 353 | |
| 354 | $fixed_offset = $this->value - 10; |
| 355 | $proportional = (int) round( $this->value * 0.85 ); |
| 356 | $animation_from = max( 0, min( $fixed_offset, $proportional ) ); |
| 357 | |
| 358 | return sprintf( |
| 359 | '<div %s><div class="tutor-progress-bar-fill" style="--tutor-progress-start: %d%%; --tutor-progress-width: %d%%;"></div></div>', |
| 360 | $attributes, |
| 361 | $animation_from, |
| 362 | $this->value |
| 363 | ); |
| 364 | } |
| 365 | |
| 366 | /** |
| 367 | * Render progress circle HTML. |
| 368 | * |
| 369 | * @since 4.0.0 |
| 370 | * |
| 371 | * @return string HTML output. |
| 372 | */ |
| 373 | protected function render_circle() { |
| 374 | // Build Alpine.js x-data attribute. |
| 375 | $alpine_data = array(); |
| 376 | |
| 377 | if ( 'progress' === $this->state ) { |
| 378 | $alpine_data['value'] = $this->value; |
| 379 | $alpine_data['type'] = 'progress'; |
| 380 | } else { |
| 381 | $alpine_data['type'] = $this->state; |
| 382 | } |
| 383 | |
| 384 | $alpine_data['size'] = $this->size; |
| 385 | $alpine_data['background'] = $this->background; |
| 386 | $alpine_data['strokeColor'] = $this->stroke_color; |
| 387 | $alpine_data['progressStrokeColor'] = $this->progress_stroke_color; |
| 388 | $alpine_data['showLabel'] = $this->show_label; |
| 389 | $alpine_data['label'] = $this->label; |
| 390 | $alpine_data['animated'] = $this->animated; |
| 391 | $alpine_data['duration'] = $this->duration; |
| 392 | |
| 393 | // Convert to JSON for x-data. |
| 394 | $alpine_json = wp_json_encode( $alpine_data ); |
| 395 | |
| 396 | // Merge attributes. |
| 397 | $this->attributes['x-data'] = sprintf( 'tutorStatics(%s)', $alpine_json ); |
| 398 | |
| 399 | $attributes = $this->get_attributes_string(); |
| 400 | |
| 401 | return sprintf( |
| 402 | '<div %s><div x-html="render()"></div></div>', |
| 403 | $attributes |
| 404 | ); |
| 405 | } |
| 406 | |
| 407 | /** |
| 408 | * Get the final progress HTML. |
| 409 | * |
| 410 | * @since 4.0.0 |
| 411 | * |
| 412 | * @return string HTML output. |
| 413 | */ |
| 414 | public function get(): string { |
| 415 | if ( 'circle' === $this->type ) { |
| 416 | $this->component_string = $this->render_circle(); |
| 417 | } else { |
| 418 | $this->component_string = $this->render_bar(); |
| 419 | } |
| 420 | |
| 421 | return $this->component_string; |
| 422 | } |
| 423 | } |
| 424 |