PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.78
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.78
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Quick_Product_Slider / Quick_Product_Slider.php

Quick_Product_Slider.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.78, at includes/widgets/Quick_Product_Slider/Quick_Product_Slider.php

2,135 lines 70.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Quick Product Slider Widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Border;
12 use Elementor\Group_Control_Box_Shadow;
13 use Elementor\Group_Control_Image_Size;
14 use Elementor\Group_Control_Typography;
15 use Elementor\Widget_Base;
16 use WP_Query;
17
18 if (!defined('ABSPATH')) {
19 exit;
20 }
21
22 /**
23 * Renders the Quick Product Slider widget.
24 */
25 class Quick_Product_Slider extends Widget_Base
26 {
27 /**
28 * Widget slug.
29 *
30 * @return string
31 */
32 public function get_name(): string
33 {
34 return 'king-addons-quick-product-slider';
35 }
36
37 /**
38 * Widget title.
39 *
40 * @return string
41 */
42 public function get_title(): string
43 {
44 return esc_html__('Quick Product Slider', 'king-addons');
45 }
46
47 /**
48 * Widget icon.
49 *
50 * @return string
51 */
52 public function get_icon(): string
53 {
54 return 'king-addons-icon king-addons-quick-product-slider';
55 }
56
57 /**
58 * Script dependencies.
59 *
60 * @return array<int, string>
61 */
62 public function get_script_depends(): array
63 {
64 $deps = [
65 KING_ADDONS_ASSETS_UNIQUE_KEY . '-swiper-swiper',
66 KING_ADDONS_ASSETS_UNIQUE_KEY . '-quick-product-slider-script',
67 ];
68
69 if (class_exists('\WooCommerce') && function_exists('wp_script_is') && wp_script_is('wc-add-to-cart', 'registered')) {
70 $deps[] = 'wc-add-to-cart';
71 }
72
73 return $deps;
74 }
75
76 /**
77 * Style dependencies.
78 *
79 * @return array<int, string>
80 */
81 public function get_style_depends(): array
82 {
83 return [
84 KING_ADDONS_ASSETS_UNIQUE_KEY . '-swiper-swiper',
85 KING_ADDONS_ASSETS_UNIQUE_KEY . '-quick-product-slider-style',
86 ];
87 }
88
89 /**
90 * Widget categories.
91 *
92 * @return array<int, string>
93 */
94 public function get_categories(): array
95 {
96 return ['king-addons'];
97 }
98
99 /**
100 * Widget keywords.
101 *
102 * @return array<int, string>
103 */
104 public function get_keywords(): array
105 {
106 return ['woocommerce', 'product', 'quick', 'slider', 'shop'];
107 }
108
109 public function get_custom_help_url()
110 {
111 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
112 }
113
114 /**
115 * Register controls.
116 *
117 * @return void
118 */
119 public function register_controls(): void
120 {
121 $this->register_query_controls();
122 $this->register_slider_controls();
123 $this->register_interaction_controls();
124 $this->register_navigation_controls();
125 $this->register_pagination_controls();
126 $this->register_display_controls();
127 $this->register_style_card_controls();
128 $this->register_style_text_controls();
129 $this->register_style_rating_controls();
130 $this->register_style_badge_controls();
131 $this->register_style_button_controls();
132 $this->register_style_view_cart_controls();
133 $this->register_style_navigation_controls();
134 $this->register_style_pagination_controls();
135 $this->register_pro_notice_controls();
136 }
137
138 /**
139 * Interaction controls.
140 *
141 * @return void
142 */
143 protected function register_interaction_controls(): void
144 {
145 $this->start_controls_section(
146 'kng_interaction_section',
147 [
148 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Animations', 'king-addons'),
149 'tab' => Controls_Manager::TAB_CONTENT,
150 ]
151 );
152
153 $this->add_control(
154 'kng_hover_animation',
155 [
156 'label' => esc_html__('Hover Animation', 'king-addons'),
157 'type' => Controls_Manager::SELECT,
158 'default' => 'hover-small-lift',
159 'options' => [
160 'none' => esc_html__('None', 'king-addons'),
161 'hover-small-lift' => esc_html__('Small Lift', 'king-addons'),
162 'hover-lift' => esc_html__('Lift', 'king-addons'),
163 'hover-zoom' => esc_html__('Image Zoom', 'king-addons'),
164 'hover-tilt' => esc_html__('Tilt', 'king-addons'),
165 'hover-float' => esc_html__('Float', 'king-addons'),
166 'hover-scale-fade' => esc_html__('Scale & Fade', 'king-addons'),
167 ],
168 ]
169 );
170
171 $this->end_controls_section();
172 }
173
174 /**
175 * Render widget output.
176 *
177 * @return void
178 */
179 public function render(): void
180 {
181 if (!class_exists('\WooCommerce')) {
182 return;
183 }
184
185 $settings = $this->get_settings_for_display();
186 $query = $this->build_query($settings);
187
188 if (!$query->have_posts()) {
189 wp_reset_postdata();
190 return;
191 }
192
193 $data_attributes = $this->get_slider_data_attributes($settings);
194 $wrapper_classes = $this->get_wrapper_classes($settings);
195
196 ?>
197 <div class="<?php echo esc_attr(implode(' ', $wrapper_classes)); ?>">
198 <div class="king-addons-quick-product-slider__track swiper" <?php echo $data_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
199 <div class="king-addons-quick-product-slider__wrapper swiper-wrapper">
200 <?php
201 while ($query->have_posts()) :
202 $query->the_post();
203 $product = wc_get_product(get_the_ID());
204 if ($product) {
205 $this->render_slide($settings, $product);
206 }
207 endwhile;
208 ?>
209 </div>
210 <?php if (($settings['kng_show_pagination'] ?? 'yes') === 'yes') : ?>
211 <div class="king-addons-quick-product-slider__pagination swiper-pagination" aria-label="<?php echo esc_attr__('Slider pagination', 'king-addons'); ?>"></div>
212 <?php endif; ?>
213 </div>
214 <?php if (($settings['kng_show_navigation'] ?? 'yes') === 'yes') : ?>
215 <div class="king-addons-quick-product-slider__navigation" aria-label="<?php echo esc_attr__('Slider navigation', 'king-addons'); ?>">
216 <button type="button" class="king-addons-quick-product-slider__arrow king-addons-quick-product-slider__arrow--prev swiper-button-prev" aria-label="<?php echo esc_attr__('Previous', 'king-addons'); ?>">
217 <span class="king-addons-quick-product-slider__arrow-icon" aria-hidden="true"></span>
218 </button>
219 <button type="button" class="king-addons-quick-product-slider__arrow king-addons-quick-product-slider__arrow--next swiper-button-next" aria-label="<?php echo esc_attr__('Next', 'king-addons'); ?>">
220 <span class="king-addons-quick-product-slider__arrow-icon" aria-hidden="true"></span>
221 </button>
222 </div>
223 <?php endif; ?>
224 </div>
225 <?php
226
227 wp_reset_postdata();
228 }
229
230 /**
231 * Query controls.
232 *
233 * @return void
234 */
235 protected function register_query_controls(): void
236 {
237 $this->start_controls_section(
238 'kng_query_section',
239 [
240 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Query', 'king-addons'),
241 'tab' => Controls_Manager::TAB_CONTENT,
242 ]
243 );
244
245 $this->add_control(
246 'kng_products_per_page',
247 [
248 'label' => esc_html__('Products Number', 'king-addons'),
249 'type' => Controls_Manager::NUMBER,
250 'min' => 1,
251 'max' => 12,
252 'step' => 1,
253 'default' => 6,
254 'description' => esc_html__('Free version limited to 12 products.', 'king-addons'),
255 ]
256 );
257
258 $this->add_control(
259 'kng_orderby',
260 [
261 'label' => esc_html__('Order By', 'king-addons'),
262 'type' => Controls_Manager::SELECT,
263 'default' => 'date',
264 'options' => [
265 'date' => esc_html__('Date', 'king-addons'),
266 'title' => esc_html__('Title', 'king-addons'),
267 'price' => esc_html__('Price', 'king-addons'),
268 'popularity' => esc_html__('Popularity', 'king-addons'),
269 'rating' => esc_html__('Rating', 'king-addons'),
270 'rand' => esc_html__('Random', 'king-addons'),
271 ],
272 ]
273 );
274
275 $this->add_control(
276 'kng_order',
277 [
278 'label' => esc_html__('Order', 'king-addons'),
279 'type' => Controls_Manager::SELECT,
280 'default' => 'DESC',
281 'options' => [
282 'DESC' => esc_html__('DESC', 'king-addons'),
283 'ASC' => esc_html__('ASC', 'king-addons'),
284 ],
285 ]
286 );
287
288 $this->add_control(
289 'kng_categories',
290 [
291 'label' => sprintf(__('Categories %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
292 'type' => Controls_Manager::TEXT,
293 'description' => esc_html__('Comma-separated slugs.', 'king-addons'),
294 'classes' => 'king-addons-pro-control no-distance',
295 ]
296 );
297
298 $this->end_controls_section();
299 }
300
301 /**
302 * Slider controls.
303 *
304 * @return void
305 */
306 protected function register_slider_controls(): void
307 {
308 $this->start_controls_section(
309 'kng_slider_section',
310 [
311 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Slider Settings', 'king-addons'),
312 'tab' => Controls_Manager::TAB_CONTENT,
313 ]
314 );
315
316 $this->add_control(
317 'kng_slides_per_view',
318 [
319 'label' => esc_html__('Slides Per View', 'king-addons'),
320 'type' => Controls_Manager::NUMBER,
321 'min' => 1,
322 'max' => 6,
323 'step' => 1,
324 'default' => 3,
325 ]
326 );
327
328 $this->add_control(
329 'kng_slides_per_view_tablet',
330 [
331 'label' => esc_html__('Slides Per View (Tablet)', 'king-addons'),
332 'type' => Controls_Manager::NUMBER,
333 'min' => 1,
334 'max' => 6,
335 'step' => 1,
336 'default' => 2,
337 ]
338 );
339
340 $this->add_control(
341 'kng_slides_per_view_mobile',
342 [
343 'label' => esc_html__('Slides Per View (Mobile)', 'king-addons'),
344 'type' => Controls_Manager::NUMBER,
345 'min' => 1,
346 'max' => 6,
347 'step' => 1,
348 'default' => 1,
349 ]
350 );
351
352 $this->add_control(
353 'kng_space_between',
354 [
355 'label' => esc_html__('Space Between', 'king-addons'),
356 'type' => Controls_Manager::NUMBER,
357 'min' => 0,
358 'max' => 80,
359 'step' => 1,
360 'default' => 20,
361 ]
362 );
363
364 $this->add_control(
365 'kng_slides_per_group',
366 [
367 'label' => esc_html__('Slides Per Group', 'king-addons'),
368 'type' => Controls_Manager::NUMBER,
369 'min' => 1,
370 'max' => 6,
371 'step' => 1,
372 'default' => 1,
373 ]
374 );
375
376 $this->add_control(
377 'kng_loop',
378 [
379 'label' => esc_html__('Loop', 'king-addons'),
380 'type' => Controls_Manager::SWITCHER,
381 'return_value' => 'yes',
382 'default' => 'yes',
383 ]
384 );
385
386 $this->add_control(
387 'kng_autoplay',
388 [
389 'label' => esc_html__('Autoplay', 'king-addons'),
390 'type' => Controls_Manager::SWITCHER,
391 'return_value' => 'yes',
392 'default' => '',
393 ]
394 );
395
396 $this->add_control(
397 'kng_autoplay_delay',
398 [
399 'label' => esc_html__('Autoplay Delay (ms)', 'king-addons'),
400 'type' => Controls_Manager::NUMBER,
401 'min' => 1000,
402 'max' => 10000,
403 'step' => 100,
404 'default' => 3200,
405 'condition' => [
406 'kng_autoplay' => 'yes',
407 ],
408 ]
409 );
410
411 $this->add_control(
412 'kng_autoplay_pause_on_hover',
413 [
414 'label' => esc_html__('Pause on Hover', 'king-addons'),
415 'type' => Controls_Manager::SWITCHER,
416 'return_value' => 'yes',
417 'default' => '',
418 'condition' => [
419 'kng_autoplay' => 'yes',
420 ],
421 ]
422 );
423
424 $this->add_control(
425 'kng_autoplay_stop_on_interaction',
426 [
427 'label' => esc_html__('Stop on Interaction', 'king-addons'),
428 'type' => Controls_Manager::SWITCHER,
429 'return_value' => 'yes',
430 'default' => '',
431 'condition' => [
432 'kng_autoplay' => 'yes',
433 ],
434 ]
435 );
436
437 $this->add_control(
438 'kng_speed',
439 [
440 'label' => esc_html__('Transition Speed (ms)', 'king-addons'),
441 'type' => Controls_Manager::NUMBER,
442 'min' => 100,
443 'max' => 5000,
444 'step' => 50,
445 'default' => 600,
446 ]
447 );
448
449 $this->end_controls_section();
450 }
451
452 /**
453 * Navigation controls (layout and placement).
454 *
455 * @return void
456 */
457 protected function register_navigation_controls(): void
458 {
459 $this->start_controls_section(
460 'kng_navigation_section',
461 [
462 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Navigation', 'king-addons'),
463 'tab' => Controls_Manager::TAB_CONTENT,
464 ]
465 );
466
467 $this->add_control(
468 'kng_show_navigation',
469 [
470 'label' => esc_html__('Show Arrows', 'king-addons'),
471 'type' => Controls_Manager::SWITCHER,
472 'return_value' => 'yes',
473 'default' => 'yes',
474 ]
475 );
476
477 $this->add_control(
478 'kng_navigation_position',
479 [
480 'label' => esc_html__('Position', 'king-addons'),
481 'type' => Controls_Manager::SELECT,
482 'default' => 'outside',
483 'options' => [
484 'outside' => esc_html__('Outside', 'king-addons'),
485 'inside' => esc_html__('Inside', 'king-addons'),
486 ],
487 'condition' => [
488 'kng_show_navigation' => 'yes',
489 ],
490 ]
491 );
492
493 $this->add_control(
494 'kng_navigation_alignment',
495 [
496 'label' => esc_html__('Alignment', 'king-addons'),
497 'type' => Controls_Manager::CHOOSE,
498 'options' => [
499 'flex-start' => [
500 'title' => esc_html__('Top', 'king-addons'),
501 'icon' => 'eicon-v-align-top',
502 ],
503 'center' => [
504 'title' => esc_html__('Center', 'king-addons'),
505 'icon' => 'eicon-v-align-middle',
506 ],
507 'flex-end' => [
508 'title' => esc_html__('Bottom', 'king-addons'),
509 'icon' => 'eicon-v-align-bottom',
510 ],
511 ],
512 'toggle' => false,
513 'default' => 'center',
514 'condition' => [
515 'kng_show_navigation' => 'yes',
516 ],
517 ]
518 );
519
520 $this->add_responsive_control(
521 'kng_navigation_offset',
522 [
523 'label' => esc_html__('Offset', 'king-addons'),
524 'type' => Controls_Manager::SLIDER,
525 'size_units' => ['px'],
526 'range' => [
527 'px' => [
528 'min' => 0,
529 'max' => 80,
530 ],
531 ],
532 'default' => [
533 'size' => 25,
534 'unit' => 'px',
535 ],
536 'condition' => [
537 'kng_show_navigation' => 'yes',
538 ],
539 'selectors' => [
540 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-nav-offset: {{SIZE}}{{UNIT}};',
541 ],
542 ]
543 );
544
545 $this->add_control(
546 'kng_navigation_hide_tablet',
547 [
548 'label' => esc_html__('Hide on Tablet', 'king-addons'),
549 'type' => Controls_Manager::SWITCHER,
550 'label_on' => esc_html__('Yes', 'king-addons'),
551 'label_off' => esc_html__('No', 'king-addons'),
552 'return_value' => 'yes',
553 'condition' => [
554 'kng_show_navigation' => 'yes',
555 ],
556 ]
557 );
558
559 $this->add_control(
560 'kng_navigation_hide_mobile',
561 [
562 'label' => esc_html__('Hide on Mobile', 'king-addons'),
563 'type' => Controls_Manager::SWITCHER,
564 'label_on' => esc_html__('Yes', 'king-addons'),
565 'label_off' => esc_html__('No', 'king-addons'),
566 'return_value' => 'yes',
567 'condition' => [
568 'kng_show_navigation' => 'yes',
569 ],
570 ]
571 );
572
573 $this->add_control(
574 'kng_navigation_inside_padding',
575 [
576 'label' => esc_html__('Inside Padding', 'king-addons'),
577 'type' => Controls_Manager::SLIDER,
578 'size_units' => ['px'],
579 'range' => [
580 'px' => [
581 'min' => 0,
582 'max' => 80,
583 ],
584 ],
585 'default' => [
586 'size' => 12,
587 'unit' => 'px',
588 ],
589 'condition' => [
590 'kng_show_navigation' => 'yes',
591 'kng_navigation_position' => 'inside',
592 ],
593 'selectors' => [
594 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-nav-padding: {{SIZE}}{{UNIT}};',
595 ],
596 ]
597 );
598
599 $this->add_control(
600 'kng_navigation_gap',
601 [
602 'label' => esc_html__('Arrows Gap', 'king-addons'),
603 'type' => Controls_Manager::SLIDER,
604 'size_units' => ['px'],
605 'range' => [
606 'px' => [
607 'min' => 4,
608 'max' => 80,
609 ],
610 ],
611 'default' => [
612 'size' => 12,
613 'unit' => 'px',
614 ],
615 'condition' => [
616 'kng_show_navigation' => 'yes',
617 ],
618 'selectors' => [
619 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-nav-gap: {{SIZE}}{{UNIT}};',
620 ],
621 ]
622 );
623
624 $this->end_controls_section();
625 }
626
627 /**
628 * Pagination controls (layout and placement).
629 *
630 * @return void
631 */
632 protected function register_pagination_controls(): void
633 {
634 $this->start_controls_section(
635 'kng_pagination_section',
636 [
637 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Pagination', 'king-addons'),
638 'tab' => Controls_Manager::TAB_CONTENT,
639 ]
640 );
641
642 $this->add_control(
643 'kng_show_pagination',
644 [
645 'label' => esc_html__('Show Pagination', 'king-addons'),
646 'type' => Controls_Manager::SWITCHER,
647 'return_value' => 'yes',
648 'default' => 'yes',
649 ]
650 );
651
652 $this->add_control(
653 'kng_pagination_position',
654 [
655 'label' => esc_html__('Position', 'king-addons'),
656 'type' => Controls_Manager::SELECT,
657 'default' => 'outside',
658 'options' => [
659 'outside' => esc_html__('Outside', 'king-addons'),
660 'inside' => esc_html__('Inside', 'king-addons'),
661 ],
662 'condition' => [
663 'kng_show_pagination' => 'yes',
664 ],
665 ]
666 );
667
668 $this->add_control(
669 'kng_pagination_alignment',
670 [
671 'label' => esc_html__('Alignment', 'king-addons'),
672 'type' => Controls_Manager::CHOOSE,
673 'options' => [
674 'flex-start' => [
675 'title' => esc_html__('Start', 'king-addons'),
676 'icon' => 'eicon-h-align-left',
677 ],
678 'center' => [
679 'title' => esc_html__('Center', 'king-addons'),
680 'icon' => 'eicon-h-align-center',
681 ],
682 'flex-end' => [
683 'title' => esc_html__('End', 'king-addons'),
684 'icon' => 'eicon-h-align-right',
685 ],
686 ],
687 'toggle' => false,
688 'default' => 'center',
689 'condition' => [
690 'kng_show_pagination' => 'yes',
691 ],
692 ]
693 );
694
695 $this->add_responsive_control(
696 'kng_pagination_offset',
697 [
698 'label' => esc_html__('Offset', 'king-addons'),
699 'type' => Controls_Manager::SLIDER,
700 'size_units' => ['px'],
701 'range' => [
702 'px' => [
703 'min' => 0,
704 'max' => 80,
705 ],
706 ],
707 'default' => [
708 'size' => 14,
709 'unit' => 'px',
710 ],
711 'condition' => [
712 'kng_show_pagination' => 'yes',
713 ],
714 'selectors' => [
715 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-pagination-offset: {{SIZE}}{{UNIT}};',
716 ],
717 ]
718 );
719
720 $this->add_responsive_control(
721 'kng_pagination_gap',
722 [
723 'label' => esc_html__('Dots Gap', 'king-addons'),
724 'type' => Controls_Manager::SLIDER,
725 'size_units' => ['px'],
726 'range' => [
727 'px' => [
728 'min' => 2,
729 'max' => 36,
730 ],
731 ],
732 'default' => [
733 'size' => 10,
734 'unit' => 'px',
735 ],
736 'condition' => [
737 'kng_show_pagination' => 'yes',
738 ],
739 'selectors' => [
740 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-pagination-gap: {{SIZE}}{{UNIT}};',
741 ],
742 ]
743 );
744
745 $this->end_controls_section();
746 }
747
748 /**
749 * Navigation style controls.
750 *
751 * @return void
752 */
753 protected function register_style_navigation_controls(): void
754 {
755 $this->start_controls_section(
756 'kng_style_navigation_section',
757 [
758 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Navigation Arrows', 'king-addons'),
759 'tab' => Controls_Manager::TAB_STYLE,
760 'condition' => [
761 'kng_show_navigation' => 'yes',
762 ],
763 ]
764 );
765
766 $this->add_control(
767 'kng_nav_size',
768 [
769 'label' => esc_html__('Size', 'king-addons'),
770 'type' => Controls_Manager::SLIDER,
771 'size_units' => ['px'],
772 'range' => [
773 'px' => ['min' => 24, 'max' => 96],
774 ],
775 'default' => [
776 'size' => 44,
777 'unit' => 'px',
778 ],
779 'selectors' => [
780 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-nav-size: {{SIZE}}{{UNIT}};',
781 ],
782 ]
783 );
784
785 $this->add_control(
786 'kng_nav_icon_size',
787 [
788 'label' => esc_html__('Icon Size', 'king-addons'),
789 'type' => Controls_Manager::SLIDER,
790 'size_units' => ['px'],
791 'range' => [
792 'px' => ['min' => 6, 'max' => 28],
793 ],
794 'default' => [
795 'size' => 12,
796 'unit' => 'px',
797 ],
798 'selectors' => [
799 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-nav-icon-size: {{SIZE}}{{UNIT}};',
800 ],
801 ]
802 );
803
804 $this->start_controls_tabs('kng_nav_tabs');
805
806 $this->start_controls_tab(
807 'kng_nav_tab_normal',
808 [
809 'label' => esc_html__('Normal', 'king-addons'),
810 ]
811 );
812
813 $this->add_control(
814 'kng_nav_color',
815 [
816 'label' => esc_html__('Icon Color', 'king-addons'),
817 'type' => Controls_Manager::COLOR,
818 'selectors' => [
819 '{{WRAPPER}} .king-addons-quick-product-slider__arrow' => 'color: {{VALUE}};',
820 ],
821 ]
822 );
823
824 $this->add_control(
825 'kng_nav_background',
826 [
827 'label' => esc_html__('Background', 'king-addons'),
828 'type' => Controls_Manager::COLOR,
829 'selectors' => [
830 '{{WRAPPER}} .king-addons-quick-product-slider__arrow' => 'background-color: {{VALUE}};',
831 ],
832 ]
833 );
834
835 $this->add_group_control(
836 Group_Control_Border::get_type(),
837 [
838 'name' => 'kng_nav_border',
839 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__arrow',
840 ]
841 );
842
843 $this->add_group_control(
844 Group_Control_Box_Shadow::get_type(),
845 [
846 'name' => 'kng_nav_shadow',
847 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__arrow',
848 ]
849 );
850
851 $this->end_controls_tab();
852
853 $this->start_controls_tab(
854 'kng_nav_tab_hover',
855 [
856 'label' => esc_html__('Hover', 'king-addons'),
857 ]
858 );
859
860 $this->add_control(
861 'kng_nav_color_hover',
862 [
863 'label' => esc_html__('Icon Color', 'king-addons'),
864 'type' => Controls_Manager::COLOR,
865 'selectors' => [
866 '{{WRAPPER}} .king-addons-quick-product-slider__arrow:hover' => 'color: {{VALUE}};',
867 ],
868 ]
869 );
870
871 $this->add_control(
872 'kng_nav_background_hover',
873 [
874 'label' => esc_html__('Background', 'king-addons'),
875 'type' => Controls_Manager::COLOR,
876 'selectors' => [
877 '{{WRAPPER}} .king-addons-quick-product-slider__arrow:hover' => 'background-color: {{VALUE}};',
878 ],
879 ]
880 );
881
882 $this->add_control(
883 'kng_nav_border_hover',
884 [
885 'label' => esc_html__('Border Color', 'king-addons'),
886 'type' => Controls_Manager::COLOR,
887 'selectors' => [
888 '{{WRAPPER}} .king-addons-quick-product-slider__arrow:hover' => 'border-color: {{VALUE}};',
889 ],
890 ]
891 );
892
893 $this->add_group_control(
894 Group_Control_Box_Shadow::get_type(),
895 [
896 'name' => 'kng_nav_shadow_hover',
897 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__arrow:hover',
898 ]
899 );
900
901 $this->end_controls_tab();
902
903 $this->end_controls_tabs();
904
905 $this->add_control(
906 'kng_nav_radius',
907 [
908 'label' => esc_html__('Border Radius', 'king-addons'),
909 'type' => Controls_Manager::SLIDER,
910 'size_units' => ['px', '%'],
911 'range' => [
912 'px' => ['min' => 0, 'max' => 80],
913 '%' => ['min' => 0, 'max' => 100],
914 ],
915 'selectors' => [
916 '{{WRAPPER}} .king-addons-quick-product-slider__arrow' => 'border-radius: {{SIZE}}{{UNIT}};',
917 ],
918 'separator' => 'before',
919 ]
920 );
921
922 $this->end_controls_section();
923 }
924
925 /**
926 * Pagination style controls.
927 *
928 * @return void
929 */
930 protected function register_style_pagination_controls(): void
931 {
932 $this->start_controls_section(
933 'kng_style_pagination_section',
934 [
935 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Pagination Dots', 'king-addons'),
936 'tab' => Controls_Manager::TAB_STYLE,
937 'condition' => [
938 'kng_show_pagination' => 'yes',
939 ],
940 ]
941 );
942
943 $this->add_control(
944 'kng_pagination_size',
945 [
946 'label' => esc_html__('Dot Size', 'king-addons'),
947 'type' => Controls_Manager::SLIDER,
948 'size_units' => ['px'],
949 'range' => [
950 'px' => ['min' => 4, 'max' => 24],
951 ],
952 'default' => [
953 'size' => 8,
954 'unit' => 'px',
955 ],
956 'selectors' => [
957 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-pagination-size: {{SIZE}}{{UNIT}};',
958 ],
959 ]
960 );
961
962 $this->start_controls_tabs('kng_pagination_tabs');
963
964 $this->start_controls_tab(
965 'kng_pagination_tab_normal',
966 [
967 'label' => esc_html__('Normal', 'king-addons'),
968 ]
969 );
970
971 $this->add_control(
972 'kng_pagination_color',
973 [
974 'label' => esc_html__('Color', 'king-addons'),
975 'type' => Controls_Manager::COLOR,
976 'selectors' => [
977 '{{WRAPPER}} .king-addons-quick-product-slider__pagination .swiper-pagination-bullet' => 'background-color: {{VALUE}};',
978 ],
979 ]
980 );
981
982 $this->end_controls_tab();
983
984 $this->start_controls_tab(
985 'kng_pagination_tab_active',
986 [
987 'label' => esc_html__('Active', 'king-addons'),
988 ]
989 );
990
991 $this->add_control(
992 'kng_pagination_color_active',
993 [
994 'label' => esc_html__('Color', 'king-addons'),
995 'type' => Controls_Manager::COLOR,
996 'selectors' => [
997 '{{WRAPPER}} .king-addons-quick-product-slider__pagination .swiper-pagination-bullet-active' => 'background-color: {{VALUE}};',
998 ],
999 ]
1000 );
1001
1002 $this->add_control(
1003 'kng_pagination_active_width',
1004 [
1005 'label' => esc_html__('Active Width', 'king-addons'),
1006 'type' => Controls_Manager::SLIDER,
1007 'size_units' => ['px'],
1008 'range' => [
1009 'px' => ['min' => 4, 'max' => 32],
1010 ],
1011 'selectors' => [
1012 '{{WRAPPER}} .king-addons-quick-product-slider' => '--kng-quick-product-slider-pagination-active-width: {{SIZE}}{{UNIT}};',
1013 ],
1014 ]
1015 );
1016
1017 $this->end_controls_tab();
1018
1019 $this->end_controls_tabs();
1020
1021 $this->end_controls_section();
1022 }
1023
1024 /**
1025 * Wrapper classes.
1026 *
1027 * @param array<string, mixed> $settings Settings.
1028 *
1029 * @return array<int, string>
1030 */
1031 protected function get_wrapper_classes(array $settings): array
1032 {
1033 $classes = ['king-addons-quick-product-slider'];
1034
1035 $nav_position = $settings['kng_navigation_position'] ?? 'outside';
1036 $classes[] = 'king-addons-quick-product-slider--nav-' . sanitize_html_class((string) $nav_position);
1037
1038 $nav_alignment = $settings['kng_navigation_alignment'] ?? 'center';
1039 $classes[] = 'king-addons-quick-product-slider--nav-align-' . sanitize_html_class((string) $nav_alignment);
1040
1041 if (!empty($settings['kng_navigation_hide_tablet'])) {
1042 $classes[] = 'king-addons-quick-product-slider--nav-hide-tablet';
1043 }
1044
1045 if (!empty($settings['kng_navigation_hide_mobile'])) {
1046 $classes[] = 'king-addons-quick-product-slider--nav-hide-mobile';
1047 }
1048
1049 if (!empty($settings['kng_navigation_skin']) && $settings['kng_navigation_skin'] !== 'default') {
1050 $classes[] = 'king-addons-quick-product-slider--nav-style-' . sanitize_html_class((string) $settings['kng_navigation_skin']);
1051 }
1052
1053 $pagination_position = $settings['kng_pagination_position'] ?? 'outside';
1054 $classes[] = 'king-addons-quick-product-slider--pagination-' . sanitize_html_class((string) $pagination_position);
1055
1056 $pagination_alignment = $settings['kng_pagination_alignment'] ?? 'center';
1057 $classes[] = 'king-addons-quick-product-slider--pagination-align-' . sanitize_html_class((string) $pagination_alignment);
1058
1059 if (!empty($settings['kng_pagination_skin'])) {
1060 $skin = (string) $settings['kng_pagination_skin'];
1061 if ($skin === 'pill') {
1062 $classes[] = 'king-addons-quick-product-slider--pagination-style-pill';
1063 } elseif ($skin === 'outlined') {
1064 $classes[] = 'king-addons-quick-product-slider--pagination-style-outlined';
1065 }
1066 }
1067
1068 return array_filter($classes);
1069 }
1070
1071 /**
1072 * Display controls.
1073 *
1074 * @return void
1075 */
1076 protected function register_display_controls(): void
1077 {
1078 $this->start_controls_section(
1079 'kng_display_section',
1080 [
1081 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Display', 'king-addons'),
1082 'tab' => Controls_Manager::TAB_CONTENT,
1083 ]
1084 );
1085
1086 $this->add_control(
1087 'kng_show_rating',
1088 [
1089 'label' => esc_html__('Show Rating', 'king-addons'),
1090 'type' => Controls_Manager::SWITCHER,
1091 'return_value' => 'yes',
1092 'default' => 'yes',
1093 ]
1094 );
1095
1096 $this->add_control(
1097 'kng_show_price',
1098 [
1099 'label' => esc_html__('Show Price', 'king-addons'),
1100 'type' => Controls_Manager::SWITCHER,
1101 'return_value' => 'yes',
1102 'default' => 'yes',
1103 ]
1104 );
1105
1106 $this->add_control(
1107 'kng_show_excerpt',
1108 [
1109 'label' => esc_html__('Show Short Description', 'king-addons'),
1110 'type' => Controls_Manager::SWITCHER,
1111 'return_value' => 'yes',
1112 'default' => 'yes',
1113 ]
1114 );
1115
1116 $this->add_control(
1117 'kng_show_add_to_cart',
1118 [
1119 'label' => esc_html__('Show Add to Cart', 'king-addons'),
1120 'type' => Controls_Manager::SWITCHER,
1121 'return_value' => 'yes',
1122 'default' => 'yes',
1123 ]
1124 );
1125
1126 $this->add_control(
1127 'kng_show_badge',
1128 [
1129 'label' => esc_html__('Show Sale Badge', 'king-addons'),
1130 'type' => Controls_Manager::SWITCHER,
1131 'return_value' => 'yes',
1132 'default' => 'yes',
1133 ]
1134 );
1135
1136 $this->add_control(
1137 'kng_badge_text',
1138 [
1139 'label' => esc_html__('Sale Badge Text', 'king-addons'),
1140 'type' => Controls_Manager::TEXT,
1141 'default' => esc_html__('Sale', 'king-addons'),
1142 'condition' => [
1143 'kng_show_badge' => 'yes',
1144 ],
1145 ]
1146 );
1147
1148 $this->add_control(
1149 'kng_excerpt_length',
1150 [
1151 'label' => esc_html__('Excerpt Length (words)', 'king-addons'),
1152 'type' => Controls_Manager::NUMBER,
1153 'min' => 5,
1154 'max' => 60,
1155 'step' => 1,
1156 'default' => 20,
1157 'condition' => [
1158 'kng_show_excerpt' => 'yes',
1159 ],
1160 ]
1161 );
1162
1163 $this->add_group_control(
1164 Group_Control_Image_Size::get_type(),
1165 [
1166 'name' => 'kng_image_size',
1167 'default' => 'medium',
1168 ]
1169 );
1170
1171 $this->end_controls_section();
1172 }
1173
1174 /**
1175 * Card style controls.
1176 *
1177 * @return void
1178 */
1179 protected function register_style_card_controls(): void
1180 {
1181 $this->start_controls_section(
1182 'kng_style_card_section',
1183 [
1184 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Card', 'king-addons'),
1185 'tab' => Controls_Manager::TAB_STYLE,
1186 ]
1187 );
1188
1189 $this->add_control(
1190 'kng_card_background',
1191 [
1192 'label' => esc_html__('Background', 'king-addons'),
1193 'type' => Controls_Manager::COLOR,
1194 'selectors' => [
1195 '{{WRAPPER}} .king-addons-quick-product-slider__card' => 'background-color: {{VALUE}};',
1196 ],
1197 ]
1198 );
1199
1200 $this->add_group_control(
1201 Group_Control_Border::get_type(),
1202 [
1203 'name' => 'kng_card_border',
1204 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__card',
1205 ]
1206 );
1207
1208 $this->add_control(
1209 'kng_card_radius',
1210 [
1211 'label' => esc_html__('Border Radius', 'king-addons'),
1212 'type' => Controls_Manager::SLIDER,
1213 'size_units' => ['px', '%'],
1214 'range' => [
1215 'px' => ['min' => 0, 'max' => 50],
1216 '%' => ['min' => 0, 'max' => 100],
1217 ],
1218 'selectors' => [
1219 '{{WRAPPER}} .king-addons-quick-product-slider__card' => 'border-radius: {{SIZE}}{{UNIT}};',
1220 ],
1221 ]
1222 );
1223
1224 $this->add_group_control(
1225 Group_Control_Box_Shadow::get_type(),
1226 [
1227 'name' => 'kng_card_shadow',
1228 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__card',
1229 ]
1230 );
1231
1232 $this->add_control(
1233 'kng_card_shadow_disable',
1234 [
1235 'label' => esc_html__('Disable Box Shadow', 'king-addons'),
1236 'type' => Controls_Manager::SWITCHER,
1237 'label_on' => esc_html__('Yes', 'king-addons'),
1238 'label_off' => esc_html__('No', 'king-addons'),
1239 'return_value' => 'yes',
1240 'selectors' => [
1241 '{{WRAPPER}} .king-addons-quick-product-slider__card' => 'box-shadow: none !important;',
1242 ],
1243 ]
1244 );
1245
1246 $this->add_control(
1247 'kng_card_shadow_hover_disable',
1248 [
1249 'label' => esc_html__('Disable Box Shadow on Hover', 'king-addons'),
1250 'type' => Controls_Manager::SWITCHER,
1251 'label_on' => esc_html__('Yes', 'king-addons'),
1252 'label_off' => esc_html__('No', 'king-addons'),
1253 'return_value' => 'yes',
1254 'selectors' => [
1255 '{{WRAPPER}} .king-addons-quick-product-slider__card:hover' => 'box-shadow: none !important;',
1256 ],
1257 ]
1258 );
1259
1260 $this->add_control(
1261 'kng_card_padding',
1262 [
1263 'label' => esc_html__('Padding', 'king-addons'),
1264 'type' => Controls_Manager::DIMENSIONS,
1265 'size_units' => ['px', '%', 'em'],
1266 'selectors' => [
1267 '{{WRAPPER}} .king-addons-quick-product-slider__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1268 ],
1269 ]
1270 );
1271
1272 $this->end_controls_section();
1273 }
1274
1275 /**
1276 * Text style controls.
1277 *
1278 * @return void
1279 */
1280 protected function register_style_text_controls(): void
1281 {
1282 $this->start_controls_section(
1283 'kng_style_text_section',
1284 [
1285 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text', 'king-addons'),
1286 'tab' => Controls_Manager::TAB_STYLE,
1287 ]
1288 );
1289
1290 $this->add_group_control(
1291 Group_Control_Typography::get_type(),
1292 [
1293 'name' => 'kng_title_typography',
1294 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__title',
1295 ]
1296 );
1297
1298 $this->add_control(
1299 'kng_title_color',
1300 [
1301 'label' => esc_html__('Title Color', 'king-addons'),
1302 'type' => Controls_Manager::COLOR,
1303 'selectors' => [
1304 '{{WRAPPER}} .king-addons-quick-product-slider__title a' => 'color: {{VALUE}};',
1305 ],
1306 ]
1307 );
1308
1309 $this->add_group_control(
1310 Group_Control_Typography::get_type(),
1311 [
1312 'name' => 'kng_price_typography',
1313 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__price',
1314 ]
1315 );
1316
1317 $this->add_control(
1318 'kng_price_color',
1319 [
1320 'label' => esc_html__('Price Color', 'king-addons'),
1321 'type' => Controls_Manager::COLOR,
1322 'selectors' => [
1323 '{{WRAPPER}} .king-addons-quick-product-slider__price' => 'color: {{VALUE}};',
1324 ],
1325 ]
1326 );
1327
1328 $this->add_group_control(
1329 Group_Control_Typography::get_type(),
1330 [
1331 'name' => 'kng_excerpt_typography',
1332 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__excerpt',
1333 ]
1334 );
1335
1336 $this->add_control(
1337 'kng_excerpt_color',
1338 [
1339 'label' => esc_html__('Excerpt Color', 'king-addons'),
1340 'type' => Controls_Manager::COLOR,
1341 'selectors' => [
1342 '{{WRAPPER}} .king-addons-quick-product-slider__excerpt' => 'color: {{VALUE}};',
1343 ],
1344 ]
1345 );
1346
1347 $this->end_controls_section();
1348 }
1349
1350 /**
1351 * Rating styles.
1352 *
1353 * @return void
1354 */
1355 protected function register_style_rating_controls(): void
1356 {
1357 $this->start_controls_section(
1358 'kng_style_rating_section',
1359 [
1360 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Rating', 'king-addons'),
1361 'tab' => Controls_Manager::TAB_STYLE,
1362 'condition' => [
1363 'kng_show_rating' => 'yes',
1364 ],
1365 ]
1366 );
1367
1368 $this->add_control(
1369 'kng_rating_color_empty',
1370 [
1371 'label' => esc_html__('Empty Color', 'king-addons'),
1372 'type' => Controls_Manager::COLOR,
1373 'selectors' => [
1374 '{{WRAPPER}} .king-addons-quick-product-slider__rating .star-rating' => 'color: {{VALUE}};',
1375 ],
1376 ]
1377 );
1378
1379 $this->add_control(
1380 'kng_rating_color_filled',
1381 [
1382 'label' => esc_html__('Filled Color', 'king-addons'),
1383 'type' => Controls_Manager::COLOR,
1384 'selectors' => [
1385 '{{WRAPPER}} .king-addons-quick-product-slider__rating .star-rating span' => 'color: {{VALUE}};',
1386 ],
1387 ]
1388 );
1389
1390 $this->add_control(
1391 'kng_rating_size',
1392 [
1393 'label' => esc_html__('Size', 'king-addons'),
1394 'type' => Controls_Manager::SLIDER,
1395 'size_units' => ['px'],
1396 'range' => [
1397 'px' => ['min' => 10, 'max' => 32],
1398 ],
1399 'selectors' => [
1400 '{{WRAPPER}} .king-addons-quick-product-slider__rating .star-rating' => 'font-size: {{SIZE}}{{UNIT}};',
1401 ],
1402 ]
1403 );
1404
1405 $this->end_controls_section();
1406 }
1407
1408 /**
1409 * Sale badge styles.
1410 *
1411 * @return void
1412 */
1413 protected function register_style_badge_controls(): void
1414 {
1415 $this->start_controls_section(
1416 'kng_style_badge_section',
1417 [
1418 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Sale Badge', 'king-addons'),
1419 'tab' => Controls_Manager::TAB_STYLE,
1420 'condition' => [
1421 'kng_show_badge' => 'yes',
1422 ],
1423 ]
1424 );
1425
1426 $this->add_group_control(
1427 Group_Control_Typography::get_type(),
1428 [
1429 'name' => 'kng_badge_typography',
1430 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__badge',
1431 ]
1432 );
1433
1434 $this->add_control(
1435 'kng_badge_color',
1436 [
1437 'label' => esc_html__('Text Color', 'king-addons'),
1438 'type' => Controls_Manager::COLOR,
1439 'selectors' => [
1440 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'color: {{VALUE}};',
1441 ],
1442 ]
1443 );
1444
1445 $this->add_control(
1446 'kng_badge_background',
1447 [
1448 'label' => esc_html__('Background', 'king-addons'),
1449 'type' => Controls_Manager::COLOR,
1450 'selectors' => [
1451 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'background-color: {{VALUE}};',
1452 ],
1453 ]
1454 );
1455
1456 $this->add_group_control(
1457 Group_Control_Border::get_type(),
1458 [
1459 'name' => 'kng_badge_border',
1460 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__badge',
1461 ]
1462 );
1463
1464 $this->add_group_control(
1465 Group_Control_Box_Shadow::get_type(),
1466 [
1467 'name' => 'kng_badge_shadow',
1468 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__badge',
1469 ]
1470 );
1471
1472 $this->add_control(
1473 'kng_badge_radius',
1474 [
1475 'label' => esc_html__('Border Radius', 'king-addons'),
1476 'type' => Controls_Manager::SLIDER,
1477 'size_units' => ['px', '%'],
1478 'range' => [
1479 'px' => ['min' => 0, 'max' => 50],
1480 '%' => ['min' => 0, 'max' => 100],
1481 ],
1482 'selectors' => [
1483 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'border-radius: {{SIZE}}{{UNIT}};',
1484 ],
1485 ]
1486 );
1487
1488 $this->add_responsive_control(
1489 'kng_badge_padding',
1490 [
1491 'label' => esc_html__('Padding', 'king-addons'),
1492 'type' => Controls_Manager::DIMENSIONS,
1493 'size_units' => ['px', 'em'],
1494 'selectors' => [
1495 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1496 ],
1497 ]
1498 );
1499
1500 $this->add_responsive_control(
1501 'kng_badge_offset_top',
1502 [
1503 'label' => esc_html__('Offset Top', 'king-addons'),
1504 'type' => Controls_Manager::SLIDER,
1505 'size_units' => ['px'],
1506 'range' => [
1507 'px' => ['min' => 0, 'max' => 80],
1508 ],
1509 'selectors' => [
1510 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'top: {{SIZE}}{{UNIT}};',
1511 ],
1512 ]
1513 );
1514
1515 $this->add_responsive_control(
1516 'kng_badge_offset_left',
1517 [
1518 'label' => esc_html__('Offset Left', 'king-addons'),
1519 'type' => Controls_Manager::SLIDER,
1520 'size_units' => ['px'],
1521 'range' => [
1522 'px' => ['min' => 0, 'max' => 80],
1523 ],
1524 'selectors' => [
1525 '{{WRAPPER}} .king-addons-quick-product-slider__badge' => 'left: {{SIZE}}{{UNIT}};',
1526 ],
1527 ]
1528 );
1529
1530 $this->end_controls_section();
1531 }
1532
1533 /**
1534 * Button styles.
1535 *
1536 * @return void
1537 */
1538 protected function register_style_button_controls(): void
1539 {
1540 $this->start_controls_section(
1541 'kng_style_button_section',
1542 [
1543 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Add to Cart', 'king-addons'),
1544 'tab' => Controls_Manager::TAB_STYLE,
1545 ]
1546 );
1547
1548 $this->add_group_control(
1549 Group_Control_Typography::get_type(),
1550 [
1551 'name' => 'kng_button_typography',
1552 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .button',
1553 ]
1554 );
1555
1556 $this->add_responsive_control(
1557 'kng_button_padding',
1558 [
1559 'label' => esc_html__('Padding', 'king-addons'),
1560 'type' => Controls_Manager::DIMENSIONS,
1561 'size_units' => ['px', 'em'],
1562 'selectors' => [
1563 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1564 ],
1565 ]
1566 );
1567
1568 $this->add_responsive_control(
1569 'kng_button_indicator_size',
1570 [
1571 'label' => esc_html__('Indicator Size', 'king-addons'),
1572 'type' => Controls_Manager::SLIDER,
1573 'size_units' => ['px'],
1574 'range' => [
1575 'px' => ['min' => 8, 'max' => 40],
1576 ],
1577 'selectors' => [
1578 '{{WRAPPER}} .king-addons-quick-product-slider__cta .king-addons-quick-product-slider__add-to-cart' => '--king-addons-atc-indicator-size: {{SIZE}}{{UNIT}};',
1579 ],
1580 ]
1581 );
1582
1583 $this->start_controls_tabs('kng_button_style_tabs');
1584
1585 $this->start_controls_tab(
1586 'kng_button_style_tab_normal',
1587 [
1588 'label' => esc_html__('Normal', 'king-addons'),
1589 ]
1590 );
1591
1592 $this->add_control(
1593 'kng_button_color',
1594 [
1595 'label' => esc_html__('Text Color', 'king-addons'),
1596 'type' => Controls_Manager::COLOR,
1597 'selectors' => [
1598 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button' => 'color: {{VALUE}};',
1599 ],
1600 ]
1601 );
1602
1603 $this->add_control(
1604 'kng_button_bg',
1605 [
1606 'label' => esc_html__('Background', 'king-addons'),
1607 'type' => Controls_Manager::COLOR,
1608 'selectors' => [
1609 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button' => 'background-color: {{VALUE}};',
1610 ],
1611 ]
1612 );
1613
1614 $this->add_group_control(
1615 Group_Control_Border::get_type(),
1616 [
1617 'name' => 'kng_button_border',
1618 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .button',
1619 ]
1620 );
1621
1622 $this->add_group_control(
1623 Group_Control_Box_Shadow::get_type(),
1624 [
1625 'name' => 'kng_button_shadow',
1626 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .button',
1627 ]
1628 );
1629
1630 $this->end_controls_tab();
1631
1632 $this->start_controls_tab(
1633 'kng_button_style_tab_hover',
1634 [
1635 'label' => esc_html__('Hover', 'king-addons'),
1636 ]
1637 );
1638
1639 $this->add_control(
1640 'kng_button_color_hover',
1641 [
1642 'label' => esc_html__('Hover Text Color', 'king-addons'),
1643 'type' => Controls_Manager::COLOR,
1644 'selectors' => [
1645 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button:hover' => 'color: {{VALUE}};',
1646 ],
1647 ]
1648 );
1649
1650 $this->add_control(
1651 'kng_button_bg_hover',
1652 [
1653 'label' => esc_html__('Hover Background', 'king-addons'),
1654 'type' => Controls_Manager::COLOR,
1655 'selectors' => [
1656 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button:hover' => 'background-color: {{VALUE}};',
1657 ],
1658 ]
1659 );
1660
1661 $this->add_group_control(
1662 Group_Control_Border::get_type(),
1663 [
1664 'name' => 'kng_button_border_hover',
1665 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .button:hover',
1666 ]
1667 );
1668
1669 $this->add_group_control(
1670 Group_Control_Box_Shadow::get_type(),
1671 [
1672 'name' => 'kng_button_shadow_hover',
1673 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .button:hover',
1674 ]
1675 );
1676
1677 $this->end_controls_tab();
1678
1679 $this->end_controls_tabs();
1680
1681 $this->add_control(
1682 'kng_button_radius',
1683 [
1684 'label' => esc_html__('Border Radius', 'king-addons'),
1685 'type' => Controls_Manager::SLIDER,
1686 'size_units' => ['px', '%'],
1687 'range' => [
1688 'px' => ['min' => 0, 'max' => 40],
1689 '%' => ['min' => 0, 'max' => 100],
1690 ],
1691 'selectors' => [
1692 '{{WRAPPER}} .king-addons-quick-product-slider__cta .button' => 'border-radius: {{SIZE}}{{UNIT}};',
1693 ],
1694 ]
1695 );
1696
1697 $this->end_controls_section();
1698 }
1699
1700 /**
1701 * View cart link styles (WooCommerce injects `.added_to_cart` link after AJAX add to cart).
1702 *
1703 * @return void
1704 */
1705 protected function register_style_view_cart_controls(): void
1706 {
1707 $this->start_controls_section(
1708 'kng_style_view_cart_section',
1709 [
1710 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('View Cart Link', 'king-addons'),
1711 'tab' => Controls_Manager::TAB_STYLE,
1712 ]
1713 );
1714
1715 $this->add_responsive_control(
1716 'kng_view_cart_gap',
1717 [
1718 'label' => esc_html__('Spacing From Button', 'king-addons'),
1719 'type' => Controls_Manager::SLIDER,
1720 'size_units' => ['px'],
1721 'range' => [
1722 'px' => ['min' => 0, 'max' => 60],
1723 ],
1724 'selectors' => [
1725 '{{WRAPPER}} .king-addons-quick-product-slider__cta .king-addons-quick-product-slider__add-to-cart + .added_to_cart' => 'margin-left: {{SIZE}}{{UNIT}};',
1726 ],
1727 ]
1728 );
1729
1730 $this->add_group_control(
1731 Group_Control_Typography::get_type(),
1732 [
1733 'name' => 'kng_view_cart_typography',
1734 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart',
1735 ]
1736 );
1737
1738 $this->add_responsive_control(
1739 'kng_view_cart_padding',
1740 [
1741 'label' => esc_html__('Padding', 'king-addons'),
1742 'type' => Controls_Manager::DIMENSIONS,
1743 'size_units' => ['px', 'em'],
1744 'selectors' => [
1745 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1746 ],
1747 ]
1748 );
1749
1750 $this->start_controls_tabs('kng_view_cart_style_tabs');
1751
1752 $this->start_controls_tab(
1753 'kng_view_cart_style_tab_normal',
1754 [
1755 'label' => esc_html__('Normal', 'king-addons'),
1756 ]
1757 );
1758
1759 $this->add_control(
1760 'kng_view_cart_color',
1761 [
1762 'label' => esc_html__('Text Color', 'king-addons'),
1763 'type' => Controls_Manager::COLOR,
1764 'selectors' => [
1765 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart' => 'color: {{VALUE}};',
1766 ],
1767 ]
1768 );
1769
1770 $this->add_control(
1771 'kng_view_cart_bg',
1772 [
1773 'label' => esc_html__('Background', 'king-addons'),
1774 'type' => Controls_Manager::COLOR,
1775 'selectors' => [
1776 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart' => 'background-color: {{VALUE}};',
1777 ],
1778 ]
1779 );
1780
1781 $this->add_group_control(
1782 Group_Control_Border::get_type(),
1783 [
1784 'name' => 'kng_view_cart_border',
1785 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart',
1786 ]
1787 );
1788
1789 $this->add_group_control(
1790 Group_Control_Box_Shadow::get_type(),
1791 [
1792 'name' => 'kng_view_cart_shadow',
1793 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart',
1794 ]
1795 );
1796
1797 $this->end_controls_tab();
1798
1799 $this->start_controls_tab(
1800 'kng_view_cart_style_tab_hover',
1801 [
1802 'label' => esc_html__('Hover', 'king-addons'),
1803 ]
1804 );
1805
1806 $this->add_control(
1807 'kng_view_cart_color_hover',
1808 [
1809 'label' => esc_html__('Hover Text Color', 'king-addons'),
1810 'type' => Controls_Manager::COLOR,
1811 'selectors' => [
1812 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart:hover' => 'color: {{VALUE}};',
1813 ],
1814 ]
1815 );
1816
1817 $this->add_control(
1818 'kng_view_cart_bg_hover',
1819 [
1820 'label' => esc_html__('Hover Background', 'king-addons'),
1821 'type' => Controls_Manager::COLOR,
1822 'selectors' => [
1823 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart:hover' => 'background-color: {{VALUE}};',
1824 ],
1825 ]
1826 );
1827
1828 $this->add_group_control(
1829 Group_Control_Border::get_type(),
1830 [
1831 'name' => 'kng_view_cart_border_hover',
1832 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart:hover',
1833 ]
1834 );
1835
1836 $this->add_group_control(
1837 Group_Control_Box_Shadow::get_type(),
1838 [
1839 'name' => 'kng_view_cart_shadow_hover',
1840 'selector' => '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart:hover',
1841 ]
1842 );
1843
1844 $this->end_controls_tab();
1845
1846 $this->end_controls_tabs();
1847
1848 $this->add_control(
1849 'kng_view_cart_radius',
1850 [
1851 'label' => esc_html__('Border Radius', 'king-addons'),
1852 'type' => Controls_Manager::SLIDER,
1853 'size_units' => ['px', '%'],
1854 'range' => [
1855 'px' => ['min' => 0, 'max' => 40],
1856 '%' => ['min' => 0, 'max' => 100],
1857 ],
1858 'selectors' => [
1859 '{{WRAPPER}} .king-addons-quick-product-slider__cta .added_to_cart' => 'border-radius: {{SIZE}}{{UNIT}};',
1860 ],
1861 ]
1862 );
1863
1864 $this->end_controls_section();
1865 }
1866
1867 /**
1868 * Build query for products.
1869 *
1870 * @param array<string, mixed> $settings Settings.
1871 *
1872 * @return WP_Query
1873 */
1874 protected function build_query(array $settings): WP_Query
1875 {
1876 $per_page = !empty($settings['kng_products_per_page']) ? (int) $settings['kng_products_per_page'] : 6;
1877 $per_page = min($per_page, 12);
1878
1879 $orderby_setting = $settings['kng_orderby'] ?? 'date';
1880 $meta_key = $this->get_orderby_meta_key($orderby_setting);
1881
1882 $args = [
1883 'post_type' => 'product',
1884 'posts_per_page' => $per_page,
1885 'order' => $settings['kng_order'] ?? 'DESC',
1886 'orderby' => $this->map_orderby($orderby_setting),
1887 'post_status' => 'publish',
1888 ];
1889
1890 if ($meta_key) {
1891 $args['meta_key'] = $meta_key;
1892 }
1893
1894 // Categories: gated for pro; ignored in free.
1895
1896 return new WP_Query($args);
1897 }
1898
1899 /**
1900 * Map orderby to Woo fields.
1901 *
1902 * @param string $orderby Orderby value.
1903 *
1904 * @return string
1905 */
1906 protected function map_orderby(string $orderby): string
1907 {
1908 $map = [
1909 'price' => 'meta_value_num',
1910 'popularity' => 'meta_value_num',
1911 'rating' => 'meta_value_num',
1912 'rand' => 'rand',
1913 'title' => 'title',
1914 'date' => 'date',
1915 ];
1916
1917 return $map[$orderby] ?? 'date';
1918 }
1919
1920 /**
1921 * Return meta key for meta-based orderby.
1922 *
1923 * @param string $orderby Orderby value.
1924 *
1925 * @return string|null
1926 */
1927 protected function get_orderby_meta_key(string $orderby): ?string
1928 {
1929 $map = [
1930 'price' => '_price',
1931 'popularity' => 'total_sales',
1932 'rating' => '_wc_average_rating',
1933 ];
1934
1935 return $map[$orderby] ?? null;
1936 }
1937
1938 /**
1939 * Render single slide.
1940 *
1941 * @param array<string, mixed> $settings Settings.
1942 * @param \WC_Product $product Product.
1943 *
1944 * @return void
1945 */
1946 protected function render_slide(array $settings, \WC_Product $product): void
1947 {
1948 $card_classes = ['king-addons-quick-product-slider__card'];
1949 $animation = $settings['kng_hover_animation'] ?? 'none';
1950 if ($animation !== 'none') {
1951 $card_classes[] = 'is-anim-' . sanitize_html_class((string) $animation);
1952 }
1953
1954 $show_rating = ($settings['kng_show_rating'] ?? 'yes') === 'yes';
1955 $show_price = ($settings['kng_show_price'] ?? 'yes') === 'yes';
1956 $show_excerpt = ($settings['kng_show_excerpt'] ?? 'yes') === 'yes';
1957 $show_button = ($settings['kng_show_add_to_cart'] ?? 'yes') === 'yes';
1958 $show_badge = ($settings['kng_show_badge'] ?? 'yes') === 'yes';
1959 $badge_text = !empty($settings['kng_badge_text']) ? (string) $settings['kng_badge_text'] : esc_html__('Sale', 'king-addons');
1960 $excerpt_length = !empty($settings['kng_excerpt_length']) ? max(1, (int) $settings['kng_excerpt_length']) : 20;
1961
1962 ?>
1963 <div class="king-addons-quick-product-slider__slide swiper-slide">
1964 <article class="<?php echo esc_attr(implode(' ', $card_classes)); ?>">
1965 <div class="king-addons-quick-product-slider__media">
1966 <a href="<?php the_permalink(); ?>" class="king-addons-quick-product-slider__link">
1967 <?php echo $this->get_product_image_html($product, $settings); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1968 </a>
1969 <?php if ($show_badge && $product->is_on_sale()) : ?>
1970 <span class="king-addons-quick-product-slider__badge"><?php echo esc_html($badge_text); ?></span>
1971 <?php endif; ?>
1972 </div>
1973
1974 <div class="king-addons-quick-product-slider__body">
1975 <h3 class="king-addons-quick-product-slider__title">
1976 <a href="<?php the_permalink(); ?>"><?php echo esc_html($product->get_name()); ?></a>
1977 </h3>
1978
1979 <?php if ($show_rating && wc_review_ratings_enabled()) : ?>
1980 <div class="king-addons-quick-product-slider__rating">
1981 <?php echo wc_get_rating_html($product->get_average_rating()); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1982 </div>
1983 <?php endif; ?>
1984
1985 <?php if ($show_price) : ?>
1986 <div class="king-addons-quick-product-slider__price">
1987 <?php echo $product->get_price_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1988 </div>
1989 <?php endif; ?>
1990
1991 <?php if ($show_excerpt) : ?>
1992 <div class="king-addons-quick-product-slider__excerpt">
1993 <?php echo wp_kses_post(wp_trim_words($product->get_short_description(), $excerpt_length)); ?>
1994 </div>
1995 <?php endif; ?>
1996
1997 <?php if ($show_button) : ?>
1998 <div class="king-addons-quick-product-slider__cta">
1999 <?php echo $this->render_add_to_cart_button($product); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
2000 </div>
2001 <?php endif; ?>
2002 </div>
2003 </article>
2004 </div>
2005 <?php
2006 }
2007
2008 /**
2009 * Get product image HTML with Elementor image size control.
2010 *
2011 * @param \WC_Product $product Product instance.
2012 * @param array<string, mixed> $settings Widget settings.
2013 *
2014 * @return string
2015 */
2016 protected function get_product_image_html(\WC_Product $product, array $settings): string
2017 {
2018 $image_id = $product->get_image_id();
2019
2020 if ($image_id) {
2021 $image_html = Group_Control_Image_Size::get_attachment_image_html($settings, 'kng_image_size', $image_id);
2022 if (!empty($image_html)) {
2023 return $image_html;
2024 }
2025 }
2026
2027 $fallback_size = $settings['kng_image_size_size'] ?? 'medium';
2028
2029 return $product->get_image($fallback_size);
2030 }
2031
2032 /**
2033 * Render a controlled Add to Cart button without relying on Woo shortcode.
2034 *
2035 * @param \WC_Product $product Product instance.
2036 *
2037 * @return string
2038 */
2039 protected function render_add_to_cart_button(\WC_Product $product): string
2040 {
2041 if (!$product->is_purchasable() || !$product->is_in_stock()) {
2042 return '<span class="king-addons-quick-product-slider__add-to-cart is-disabled">' . esc_html__('Unavailable', 'king-addons') . '</span>';
2043 }
2044
2045 $classes = [
2046 'king-addons-quick-product-slider__add-to-cart',
2047 'button',
2048 'product_type_' . $product->get_type(),
2049 ];
2050
2051 if ($product->supports('ajax_add_to_cart')) {
2052 $classes[] = 'ajax_add_to_cart';
2053 $classes[] = 'add_to_cart_button';
2054 }
2055
2056 $attributes = [
2057 'href' => $product->add_to_cart_url(),
2058 'data-quantity' => 1,
2059 'data-product_id' => $product->get_id(),
2060 'data-product_sku' => $product->get_sku(),
2061 'rel' => 'nofollow',
2062 'class' => implode(' ', array_filter($classes)),
2063 'aria-label' => wp_strip_all_tags($product->add_to_cart_description()),
2064 ];
2065
2066 return '<a ' . wc_implode_html_attributes($attributes) . '><span class="king-addons-quick-product-slider__add-to-cart-label">' . esc_html($product->add_to_cart_text()) . '</span></a>';
2067 }
2068
2069 /**
2070 * Build slider data attributes.
2071 *
2072 * @param array<string, mixed> $settings Settings.
2073 *
2074 * @return string
2075 */
2076 protected function get_slider_data_attributes(array $settings): string
2077 {
2078 $slides = !empty($settings['kng_slides_per_view']) ? (int) $settings['kng_slides_per_view'] : 1;
2079 $slides_tablet = !empty($settings['kng_slides_per_view_tablet']) ? (int) $settings['kng_slides_per_view_tablet'] : $slides;
2080 $slides_mobile = !empty($settings['kng_slides_per_view_mobile']) ? (int) $settings['kng_slides_per_view_mobile'] : $slides_tablet;
2081 $space = !empty($settings['kng_space_between']) ? (int) $settings['kng_space_between'] : 20;
2082 $slides_per_group = !empty($settings['kng_slides_per_group']) ? (int) $settings['kng_slides_per_group'] : 1;
2083 $speed = !empty($settings['kng_speed']) ? (int) $settings['kng_speed'] : 600;
2084 $autoplay = $settings['kng_autoplay'] ?? '';
2085 $autoplay_delay = !empty($settings['kng_autoplay_delay']) ? (int) $settings['kng_autoplay_delay'] : 3200;
2086 $autoplay_pause_on_hover = $settings['kng_autoplay_pause_on_hover'] ?? '';
2087 $autoplay_stop_on_interaction = $settings['kng_autoplay_stop_on_interaction'] ?? '';
2088 $loop = $settings['kng_loop'] ?? 'yes';
2089 $show_nav = $settings['kng_show_navigation'] ?? 'yes';
2090 $show_pagination = $settings['kng_show_pagination'] ?? 'yes';
2091
2092 $attrs = [
2093 'data-slides-per-view' => $slides,
2094 'data-slides-per-view-tablet' => $slides_tablet,
2095 'data-slides-per-view-mobile' => $slides_mobile,
2096 'data-space-between' => $space,
2097 'data-slides-per-group' => $slides_per_group,
2098 'data-speed' => $speed,
2099 'data-autoplay' => $autoplay,
2100 'data-autoplay-delay' => $autoplay_delay,
2101 'data-autoplay-pause-on-hover' => $autoplay_pause_on_hover,
2102 'data-autoplay-stop-on-interaction' => $autoplay_stop_on_interaction,
2103 'data-loop' => $loop,
2104 'data-navigation' => $show_nav,
2105 'data-pagination' => $show_pagination,
2106 ];
2107
2108 $out = [];
2109 foreach ($attrs as $key => $value) {
2110 $out[] = esc_attr($key) . '="' . esc_attr((string) $value) . '"';
2111 }
2112
2113 return implode(' ', $out);
2114 }
2115
2116 /**
2117 * Pro notice.
2118 *
2119 * @return void
2120 */
2121 public function register_pro_notice_controls(): void
2122 {
2123 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
2124 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'quick-product-slider', [
2125 'Gallery thumbs and zoom in modal',
2126 'Advanced hover animations',
2127 'Navigation/pagination skins',
2128 'Category filter and higher limits',
2129 ]);
2130 }
2131 }
2132 }
2133
2134
2135