PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.44
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.44
51.1.87 51.1.86 51.1.84 51.1.85 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 All 41 releases
king-addons / includes / widgets / Quick_Product_Slider / Quick_Product_Slider.php

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

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