PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.86
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.86
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 51.1.45 All 40 releases
king-addons / includes / widgets / Liquid_Glass_Cards / Liquid_Glass_Cards.php

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

2,020 lines 69.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Liquid Glass Cards Widget.
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Image_Size;
12 use Elementor\Group_Control_Typography;
13 use Elementor\Icons_Manager;
14 use Elementor\Plugin;
15 use Elementor\Repeater;
16 use Elementor\Utils;
17 use Elementor\Widget_Base;
18
19 if (!defined('ABSPATH')) {
20 exit;
21 }
22
23 class Liquid_Glass_Cards extends Widget_Base
24 {
25 public function get_name(): string
26 {
27 return 'king-addons-liquid-glass-cards';
28 }
29
30 public function get_title(): string
31 {
32 return esc_html__('Liquid Glass Cards', 'king-addons');
33 }
34
35 public function get_icon(): string
36 {
37 return 'king-addons-icon king-addons-liquid-glass-cards';
38 }
39
40 public function get_style_depends(): array
41 {
42 return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-liquid-glass-cards-style'];
43 }
44
45 public function get_script_depends(): array
46 {
47 if (!$this->is_pro_enabled()) {
48 return [];
49 }
50
51 return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-liquid-glass-cards-script'];
52 }
53
54 public function get_categories(): array
55 {
56 return ['king-addons'];
57 }
58
59 public function get_keywords(): array
60 {
61 return ['glass', 'liquid', 'cards', 'frosted', 'blur', 'noise', 'refraction', 'king-addons'];
62 }
63
64 public function get_custom_help_url()
65 {
66 return 'mailto:[email protected]?subject=Bug Report - King Addons&body=Please describe the issue';
67 }
68
69 protected function register_controls(): void
70 {
71 $this->register_content_controls();
72 $this->register_layout_controls();
73 $this->register_style_preset_controls();
74 $this->register_style_material_controls();
75 $this->register_style_text_controls();
76 $this->register_style_badge_controls();
77 $this->register_style_icon_controls();
78 $this->register_style_button_controls();
79 $this->register_pro_controls();
80 $this->register_pro_notice_controls();
81 }
82
83 public function render(): void
84 {
85 $settings = $this->get_settings_for_display();
86 $this->render_output($settings);
87 }
88
89 protected function register_content_controls(): void
90 {
91 $this->start_controls_section(
92 'kng_cards_section',
93 [
94 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Cards', 'king-addons'),
95 'tab' => Controls_Manager::TAB_CONTENT,
96 ]
97 );
98
99 $repeater = new Repeater();
100
101 $repeater->add_control(
102 'kng_card_title',
103 [
104 'label' => esc_html__('Title', 'king-addons'),
105 'type' => Controls_Manager::TEXT,
106 'default' => esc_html__('Glass-ready headline', 'king-addons'),
107 'dynamic' => [
108 'active' => true,
109 ],
110 'label_block' => true,
111 ]
112 );
113
114 $repeater->add_control(
115 'kng_card_subtitle',
116 [
117 'label' => esc_html__('Subtitle', 'king-addons'),
118 'type' => Controls_Manager::TEXT,
119 'default' => esc_html__('Short supporting line', 'king-addons'),
120 'dynamic' => [
121 'active' => true,
122 ],
123 'label_block' => true,
124 ]
125 );
126
127 $repeater->add_control(
128 'kng_card_description',
129 [
130 'label' => esc_html__('Description', 'king-addons'),
131 'type' => Controls_Manager::TEXTAREA,
132 'rows' => 4,
133 'default' => esc_html__('Soft glass layers with blur, noise, and subtle highlights.', 'king-addons'),
134 'dynamic' => [
135 'active' => true,
136 ],
137 ]
138 );
139
140 $repeater->add_control(
141 'kng_card_badge',
142 [
143 'label' => esc_html__('Badge', 'king-addons'),
144 'type' => Controls_Manager::TEXT,
145 'default' => esc_html__('Featured', 'king-addons'),
146 'dynamic' => [
147 'active' => true,
148 ],
149 'label_block' => true,
150 ]
151 );
152
153 $repeater->add_control(
154 'kng_card_icon',
155 [
156 'label' => esc_html__('Icon', 'king-addons'),
157 'type' => Controls_Manager::ICONS,
158 'default' => [
159 'value' => 'fas fa-star',
160 'library' => 'solid',
161 ],
162 'skin' => 'inline',
163 ]
164 );
165
166 $repeater->add_control(
167 'kng_card_image',
168 [
169 'label' => esc_html__('Image', 'king-addons'),
170 'type' => Controls_Manager::MEDIA,
171 'default' => [
172 'url' => Utils::get_placeholder_image_src(),
173 ],
174 ]
175 );
176
177 $repeater->add_control(
178 'kng_card_image_display',
179 [
180 'label' => esc_html__('Image Placement', 'king-addons'),
181 'type' => Controls_Manager::SELECT,
182 'default' => 'layer',
183 'options' => [
184 'layer' => esc_html__('Background Layer', 'king-addons'),
185 'thumb' => esc_html__('Thumbnail', 'king-addons'),
186 ],
187 ]
188 );
189
190 $repeater->add_control(
191 'kng_card_button_text',
192 [
193 'label' => esc_html__('Button Text', 'king-addons'),
194 'type' => Controls_Manager::TEXT,
195 'default' => esc_html__('Learn more', 'king-addons'),
196 'dynamic' => [
197 'active' => true,
198 ],
199 'label_block' => true,
200 ]
201 );
202
203 $repeater->add_control(
204 'kng_card_button_link',
205 [
206 'label' => esc_html__('Button Link', 'king-addons'),
207 'type' => Controls_Manager::URL,
208 'placeholder' => esc_html__('https://your-link.com', 'king-addons'),
209 ]
210 );
211
212 $repeater->add_control(
213 'kng_card_link_mode',
214 [
215 'label' => esc_html__('Card Link Mode', 'king-addons'),
216 'type' => Controls_Manager::SELECT,
217 'default' => 'button',
218 'options' => [
219 'none' => esc_html__('None', 'king-addons'),
220 'button' => esc_html__('Button Only', 'king-addons'),
221 'card' => esc_html__('Whole Card', 'king-addons'),
222 ],
223 ]
224 );
225
226 $repeater->add_control(
227 'kng_card_show_badge',
228 [
229 'label' => esc_html__('Show Badge', 'king-addons'),
230 'type' => Controls_Manager::SWITCHER,
231 'return_value' => 'yes',
232 'default' => 'yes',
233 ]
234 );
235
236 $repeater->add_control(
237 'kng_card_show_icon',
238 [
239 'label' => esc_html__('Show Icon', 'king-addons'),
240 'type' => Controls_Manager::SWITCHER,
241 'return_value' => 'yes',
242 'default' => 'yes',
243 ]
244 );
245
246 $repeater->add_control(
247 'kng_card_show_button',
248 [
249 'label' => esc_html__('Show Button', 'king-addons'),
250 'type' => Controls_Manager::SWITCHER,
251 'return_value' => 'yes',
252 'default' => 'yes',
253 ]
254 );
255
256 $this->add_group_control(
257 Group_Control_Image_Size::get_type(),
258 [
259 'name' => 'kng_card_image',
260 'default' => 'medium',
261 'separator' => 'before',
262 ]
263 );
264
265 $this->add_control(
266 'kng_cards',
267 [
268 'label' => esc_html__('Cards', 'king-addons'),
269 'type' => Controls_Manager::REPEATER,
270 'fields' => $repeater->get_controls(),
271 'default' => $this->get_default_cards(),
272 'title_field' => '{{ kng_card_title }}',
273 ]
274 );
275
276 $this->end_controls_section();
277 }
278
279 protected function register_layout_controls(): void
280 {
281 $this->start_controls_section(
282 'kng_layout_section',
283 [
284 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
285 'tab' => Controls_Manager::TAB_CONTENT,
286 ]
287 );
288
289 $this->add_responsive_control(
290 'kng_columns',
291 [
292 'label' => esc_html__('Columns', 'king-addons'),
293 'type' => Controls_Manager::NUMBER,
294 'min' => 1,
295 'max' => 6,
296 'step' => 1,
297 'default' => 3,
298 'tablet_default' => 2,
299 'mobile_default' => 1,
300 'selectors' => [
301 '{{WRAPPER}} .king-liquid-glass__grid' => 'grid-template-columns: repeat({{VALUE}}, minmax(0, 1fr));',
302 ],
303 ]
304 );
305
306 $this->add_responsive_control(
307 'kng_grid_gap',
308 [
309 'label' => esc_html__('Gap', 'king-addons'),
310 'type' => Controls_Manager::SLIDER,
311 'size_units' => ['px'],
312 'range' => [
313 'px' => [
314 'min' => 0,
315 'max' => 80,
316 ],
317 ],
318 'default' => [
319 'size' => 24,
320 'unit' => 'px',
321 ],
322 'selectors' => [
323 '{{WRAPPER}} .king-liquid-glass__grid' => 'gap: {{SIZE}}{{UNIT}};',
324 ],
325 ]
326 );
327
328 $this->add_control(
329 'kng_equal_height',
330 [
331 'label' => esc_html__('Equal Height', 'king-addons'),
332 'type' => Controls_Manager::SWITCHER,
333 'return_value' => 'yes',
334 'default' => '',
335 'render_type' => 'template',
336 ]
337 );
338
339 $this->add_control(
340 'kng_content_alignment',
341 [
342 'label' => esc_html__('Content Alignment', 'king-addons'),
343 'type' => Controls_Manager::CHOOSE,
344 'options' => [
345 'left' => [
346 'title' => esc_html__('Left', 'king-addons'),
347 'icon' => 'eicon-text-align-left',
348 ],
349 'center' => [
350 'title' => esc_html__('Center', 'king-addons'),
351 'icon' => 'eicon-text-align-center',
352 ],
353 'right' => [
354 'title' => esc_html__('Right', 'king-addons'),
355 'icon' => 'eicon-text-align-right',
356 ],
357 ],
358 'default' => 'left',
359 'toggle' => false,
360 'render_type' => 'template',
361 ]
362 );
363
364 $this->add_responsive_control(
365 'kng_card_min_height',
366 [
367 'label' => esc_html__('Card Min Height', 'king-addons'),
368 'type' => Controls_Manager::SLIDER,
369 'size_units' => ['px'],
370 'range' => [
371 'px' => [
372 'min' => 0,
373 'max' => 600,
374 ],
375 ],
376 'selectors' => [
377 '{{WRAPPER}} .king-liquid-glass__card' => 'min-height: {{SIZE}}{{UNIT}};',
378 ],
379 ]
380 );
381
382 $this->add_responsive_control(
383 'kng_card_padding',
384 [
385 'label' => esc_html__('Card Padding', 'king-addons'),
386 'type' => Controls_Manager::DIMENSIONS,
387 'size_units' => ['px', 'em'],
388 'selectors' => [
389 '{{WRAPPER}} .king-liquid-glass__content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
390 ],
391 ]
392 );
393
394 $this->add_responsive_control(
395 'kng_content_gap',
396 [
397 'label' => esc_html__('Content Spacing', 'king-addons'),
398 'type' => Controls_Manager::SLIDER,
399 'size_units' => ['px'],
400 'range' => [
401 'px' => [
402 'min' => 0,
403 'max' => 40,
404 ],
405 ],
406 'selectors' => [
407 '{{WRAPPER}} .king-liquid-glass__content' => 'gap: {{SIZE}}{{UNIT}};',
408 ],
409 ]
410 );
411
412 $this->add_responsive_control(
413 'kng_card_radius',
414 [
415 'label' => esc_html__('Border Radius', 'king-addons'),
416 'type' => Controls_Manager::SLIDER,
417 'size_units' => ['px', '%'],
418 'range' => [
419 'px' => [
420 'min' => 0,
421 'max' => 60,
422 ],
423 '%' => [
424 'min' => 0,
425 'max' => 50,
426 ],
427 ],
428 'selectors' => [
429 '{{WRAPPER}} .king-liquid-glass__card' => 'border-radius: {{SIZE}}{{UNIT}};',
430 '{{WRAPPER}} .king-liquid-glass__layer' => 'border-radius: {{SIZE}}{{UNIT}};',
431 ],
432 ]
433 );
434
435 $this->add_control(
436 'kng_shadow_style',
437 [
438 'label' => esc_html__('Shadow', 'king-addons'),
439 'type' => Controls_Manager::SELECT,
440 'default' => 'soft',
441 'options' => [
442 'off' => esc_html__('Off', 'king-addons'),
443 'soft' => esc_html__('Soft', 'king-addons'),
444 'medium' => esc_html__('Medium', 'king-addons'),
445 'strong' => esc_html__('Strong', 'king-addons'),
446 ],
447 'render_type' => 'template',
448 ]
449 );
450
451 $this->add_control(
452 'kng_title_tag',
453 [
454 'label' => esc_html__('Title HTML Tag', 'king-addons'),
455 'type' => Controls_Manager::SELECT,
456 'default' => 'h3',
457 'options' => [
458 'h2' => 'H2',
459 'h3' => 'H3',
460 'h4' => 'H4',
461 'div' => 'DIV',
462 ],
463 'separator' => 'before',
464 ]
465 );
466
467 $this->end_controls_section();
468 }
469
470 protected function register_style_preset_controls(): void
471 {
472 $this->start_controls_section(
473 'kng_preset_section',
474 [
475 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Presets', 'king-addons'),
476 'tab' => Controls_Manager::TAB_STYLE,
477 ]
478 );
479
480 $this->add_control(
481 'kng_preset',
482 [
483 'label' => esc_html__('Preset', 'king-addons'),
484 'type' => Controls_Manager::SELECT,
485 'default' => 'clear',
486 'options' => [
487 'clear' => esc_html__('Clear Glass', 'king-addons'),
488 'frosted' => esc_html__('Frosted Glass', 'king-addons'),
489 'dark' => esc_html__('Dark Glass', 'king-addons'),
490 ],
491 'render_type' => 'template',
492 ]
493 );
494
495 $this->end_controls_section();
496 }
497
498 protected function register_style_material_controls(): void
499 {
500 $this->start_controls_section(
501 'kng_material_section',
502 [
503 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Glass Material', 'king-addons'),
504 'tab' => Controls_Manager::TAB_STYLE,
505 ]
506 );
507
508 $this->add_control(
509 'kng_blur',
510 [
511 'label' => esc_html__('Blur', 'king-addons'),
512 'type' => Controls_Manager::SLIDER,
513 'size_units' => ['px'],
514 'range' => [
515 'px' => [
516 'min' => 0,
517 'max' => 30,
518 ],
519 ],
520 'render_type' => 'template',
521 ]
522 );
523
524 $this->add_control(
525 'kng_tint_mode',
526 [
527 'label' => esc_html__('Tint', 'king-addons'),
528 'type' => Controls_Manager::SELECT,
529 'default' => 'auto',
530 'options' => [
531 'auto' => esc_html__('Auto', 'king-addons'),
532 'light' => esc_html__('Light', 'king-addons'),
533 'dark' => esc_html__('Dark', 'king-addons'),
534 'custom' => esc_html__('Custom', 'king-addons'),
535 ],
536 'render_type' => 'template',
537 ]
538 );
539
540 $this->add_control(
541 'kng_tint_color',
542 [
543 'label' => esc_html__('Custom Tint', 'king-addons'),
544 'type' => Controls_Manager::COLOR,
545 'condition' => [
546 'kng_tint_mode' => 'custom',
547 ],
548 'render_type' => 'template',
549 ]
550 );
551
552 $this->add_control(
553 'kng_border_width',
554 [
555 'label' => esc_html__('Border Width', 'king-addons'),
556 'type' => Controls_Manager::SLIDER,
557 'size_units' => ['px'],
558 'range' => [
559 'px' => [
560 'min' => 0,
561 'max' => 6,
562 ],
563 ],
564 'render_type' => 'template',
565 ]
566 );
567
568 $this->add_control(
569 'kng_border_color',
570 [
571 'label' => esc_html__('Border Color', 'king-addons'),
572 'type' => Controls_Manager::COLOR,
573 'render_type' => 'template',
574 ]
575 );
576
577 $this->add_control(
578 'kng_noise_mode',
579 [
580 'label' => esc_html__('Noise Overlay', 'king-addons'),
581 'type' => Controls_Manager::SELECT,
582 'default' => 'on',
583 'options' => [
584 'on' => esc_html__('On', 'king-addons'),
585 'off' => esc_html__('Off', 'king-addons'),
586 ],
587 'render_type' => 'template',
588 ]
589 );
590
591 $this->add_control(
592 'kng_noise_opacity',
593 [
594 'label' => esc_html__('Noise Opacity', 'king-addons'),
595 'type' => Controls_Manager::SLIDER,
596 'size_units' => ['custom'],
597 'range' => [
598 'custom' => [
599 'min' => 0,
600 'max' => 0.35,
601 'step' => 0.01,
602 ],
603 ],
604 'condition' => [
605 'kng_noise_mode' => 'on',
606 ],
607 'render_type' => 'template',
608 ]
609 );
610
611 $this->add_control(
612 'kng_noise_scale',
613 [
614 'label' => esc_html__('Noise Scale', 'king-addons'),
615 'type' => Controls_Manager::SLIDER,
616 'size_units' => ['px'],
617 'range' => [
618 'px' => [
619 'min' => 20,
620 'max' => 120,
621 ],
622 ],
623 'condition' => [
624 'kng_noise_mode' => 'on',
625 ],
626 'render_type' => 'template',
627 ]
628 );
629
630 $this->add_control(
631 'kng_highlight_intensity',
632 [
633 'label' => esc_html__('Highlight Intensity', 'king-addons'),
634 'type' => Controls_Manager::SLIDER,
635 'size_units' => ['custom'],
636 'range' => [
637 'custom' => [
638 'min' => 0,
639 'max' => 1,
640 'step' => 0.01,
641 ],
642 ],
643 'render_type' => 'template',
644 ]
645 );
646
647 $this->add_control(
648 'kng_highlight_position',
649 [
650 'label' => esc_html__('Highlight Position', 'king-addons'),
651 'type' => Controls_Manager::SELECT,
652 'default' => 'top-left',
653 'options' => [
654 'top-left' => esc_html__('Top Left', 'king-addons'),
655 'top-right' => esc_html__('Top Right', 'king-addons'),
656 'center' => esc_html__('Center', 'king-addons'),
657 'bottom' => esc_html__('Bottom', 'king-addons'),
658 ],
659 'render_type' => 'template',
660 ]
661 );
662
663 $this->add_control(
664 'kng_highlight_color',
665 [
666 'label' => esc_html__('Highlight Color', 'king-addons'),
667 'type' => Controls_Manager::COLOR,
668 'render_type' => 'template',
669 ]
670 );
671
672 $this->add_control(
673 'kng_image_layer_heading',
674 [
675 'label' => esc_html__('Image Layer', 'king-addons'),
676 'type' => Controls_Manager::HEADING,
677 'separator' => 'before',
678 ]
679 );
680
681 $this->add_control(
682 'kng_image_opacity',
683 [
684 'label' => esc_html__('Image Opacity', 'king-addons'),
685 'type' => Controls_Manager::SLIDER,
686 'size_units' => ['custom'],
687 'range' => [
688 'custom' => [
689 'min' => 0,
690 'max' => 1,
691 'step' => 0.01,
692 ],
693 ],
694 'render_type' => 'template',
695 ]
696 );
697
698 $this->add_control(
699 'kng_image_blend',
700 [
701 'label' => esc_html__('Image Blend Mode', 'king-addons'),
702 'type' => Controls_Manager::SELECT,
703 'default' => 'screen',
704 'options' => [
705 'normal' => esc_html__('Normal', 'king-addons'),
706 'screen' => esc_html__('Screen', 'king-addons'),
707 'overlay' => esc_html__('Overlay', 'king-addons'),
708 'soft-light' => esc_html__('Soft Light', 'king-addons'),
709 'multiply' => esc_html__('Multiply', 'king-addons'),
710 ],
711 'render_type' => 'template',
712 ]
713 );
714
715 $this->end_controls_section();
716 }
717
718 protected function register_style_text_controls(): void
719 {
720 $this->start_controls_section(
721 'kng_typography_section',
722 [
723 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Typography', 'king-addons'),
724 'tab' => Controls_Manager::TAB_STYLE,
725 ]
726 );
727
728 $this->add_group_control(
729 Group_Control_Typography::get_type(),
730 [
731 'name' => 'kng_title_typography',
732 'label' => esc_html__('Title Typography', 'king-addons'),
733 'selector' => '{{WRAPPER}} .king-liquid-glass__title',
734 ]
735 );
736
737 $this->add_control(
738 'kng_title_color',
739 [
740 'label' => esc_html__('Title Color', 'king-addons'),
741 'type' => Controls_Manager::COLOR,
742 'selectors' => [
743 '{{WRAPPER}} .king-liquid-glass__title' => 'color: {{VALUE}};',
744 ],
745 ]
746 );
747
748 $this->add_group_control(
749 Group_Control_Typography::get_type(),
750 [
751 'name' => 'kng_subtitle_typography',
752 'label' => esc_html__('Subtitle Typography', 'king-addons'),
753 'selector' => '{{WRAPPER}} .king-liquid-glass__subtitle',
754 ]
755 );
756
757 $this->add_control(
758 'kng_subtitle_color',
759 [
760 'label' => esc_html__('Subtitle Color', 'king-addons'),
761 'type' => Controls_Manager::COLOR,
762 'selectors' => [
763 '{{WRAPPER}} .king-liquid-glass__subtitle' => 'color: {{VALUE}};',
764 ],
765 ]
766 );
767
768 $this->add_group_control(
769 Group_Control_Typography::get_type(),
770 [
771 'name' => 'kng_description_typography',
772 'label' => esc_html__('Description Typography', 'king-addons'),
773 'selector' => '{{WRAPPER}} .king-liquid-glass__description',
774 ]
775 );
776
777 $this->add_control(
778 'kng_description_color',
779 [
780 'label' => esc_html__('Description Color', 'king-addons'),
781 'type' => Controls_Manager::COLOR,
782 'selectors' => [
783 '{{WRAPPER}} .king-liquid-glass__description' => 'color: {{VALUE}};',
784 ],
785 ]
786 );
787
788 $this->end_controls_section();
789 }
790
791 protected function register_style_badge_controls(): void
792 {
793 $this->start_controls_section(
794 'kng_badge_section',
795 [
796 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Badge', 'king-addons'),
797 'tab' => Controls_Manager::TAB_STYLE,
798 ]
799 );
800
801 $this->add_group_control(
802 Group_Control_Typography::get_type(),
803 [
804 'name' => 'kng_badge_typography',
805 'label' => esc_html__('Typography', 'king-addons'),
806 'selector' => '{{WRAPPER}} .king-liquid-glass__badge',
807 ]
808 );
809
810 $this->add_control(
811 'kng_badge_color',
812 [
813 'label' => esc_html__('Text Color', 'king-addons'),
814 'type' => Controls_Manager::COLOR,
815 'selectors' => [
816 '{{WRAPPER}} .king-liquid-glass__badge' => 'color: {{VALUE}};',
817 ],
818 ]
819 );
820
821 $this->add_control(
822 'kng_badge_background',
823 [
824 'label' => esc_html__('Background', 'king-addons'),
825 'type' => Controls_Manager::COLOR,
826 'selectors' => [
827 '{{WRAPPER}} .king-liquid-glass__badge' => 'background-color: {{VALUE}};',
828 ],
829 ]
830 );
831
832 $this->add_control(
833 'kng_badge_radius',
834 [
835 'label' => esc_html__('Border Radius', 'king-addons'),
836 'type' => Controls_Manager::SLIDER,
837 'size_units' => ['px', '%'],
838 'range' => [
839 'px' => [
840 'min' => 0,
841 'max' => 30,
842 ],
843 '%' => [
844 'min' => 0,
845 'max' => 100,
846 ],
847 ],
848 'selectors' => [
849 '{{WRAPPER}} .king-liquid-glass__badge' => 'border-radius: {{SIZE}}{{UNIT}};',
850 ],
851 ]
852 );
853
854 $this->add_responsive_control(
855 'kng_badge_padding',
856 [
857 'label' => esc_html__('Padding', 'king-addons'),
858 'type' => Controls_Manager::DIMENSIONS,
859 'size_units' => ['px', 'em'],
860 'selectors' => [
861 '{{WRAPPER}} .king-liquid-glass__badge' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
862 ],
863 ]
864 );
865
866 $this->end_controls_section();
867 }
868
869 protected function register_style_icon_controls(): void
870 {
871 $this->start_controls_section(
872 'kng_icon_section',
873 [
874 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Icon', 'king-addons'),
875 'tab' => Controls_Manager::TAB_STYLE,
876 ]
877 );
878
879 $this->add_control(
880 'kng_icon_size',
881 [
882 'label' => esc_html__('Size', 'king-addons'),
883 'type' => Controls_Manager::SLIDER,
884 'size_units' => ['px'],
885 'range' => [
886 'px' => [
887 'min' => 12,
888 'max' => 80,
889 ],
890 ],
891 'selectors' => [
892 '{{WRAPPER}} .king-liquid-glass__icon' => 'font-size: {{SIZE}}{{UNIT}};',
893 '{{WRAPPER}} .king-liquid-glass__icon svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
894 ],
895 ]
896 );
897
898 $this->add_control(
899 'kng_icon_color',
900 [
901 'label' => esc_html__('Color', 'king-addons'),
902 'type' => Controls_Manager::COLOR,
903 'selectors' => [
904 '{{WRAPPER}} .king-liquid-glass__icon' => 'color: {{VALUE}};',
905 '{{WRAPPER}} .king-liquid-glass__icon svg' => 'fill: {{VALUE}};',
906 ],
907 ]
908 );
909
910 $this->end_controls_section();
911 }
912
913 protected function register_style_button_controls(): void
914 {
915 $this->start_controls_section(
916 'kng_button_section',
917 [
918 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Button', 'king-addons'),
919 'tab' => Controls_Manager::TAB_STYLE,
920 ]
921 );
922
923 $this->add_group_control(
924 Group_Control_Typography::get_type(),
925 [
926 'name' => 'kng_button_typography',
927 'label' => esc_html__('Typography', 'king-addons'),
928 'selector' => '{{WRAPPER}} .king-liquid-glass__button',
929 ]
930 );
931
932 $this->start_controls_tabs('kng_button_tabs');
933
934 $this->start_controls_tab(
935 'kng_button_tab_normal',
936 [
937 'label' => esc_html__('Normal', 'king-addons'),
938 ]
939 );
940
941 $this->add_control(
942 'kng_button_text_color',
943 [
944 'label' => esc_html__('Text Color', 'king-addons'),
945 'type' => Controls_Manager::COLOR,
946 'selectors' => [
947 '{{WRAPPER}} .king-liquid-glass__button' => 'color: {{VALUE}};',
948 ],
949 ]
950 );
951
952 $this->add_control(
953 'kng_button_background',
954 [
955 'label' => esc_html__('Background', 'king-addons'),
956 'type' => Controls_Manager::COLOR,
957 'selectors' => [
958 '{{WRAPPER}} .king-liquid-glass__button' => 'background-color: {{VALUE}};',
959 ],
960 ]
961 );
962
963 $this->add_control(
964 'kng_button_border_color',
965 [
966 'label' => esc_html__('Border Color', 'king-addons'),
967 'type' => Controls_Manager::COLOR,
968 'selectors' => [
969 '{{WRAPPER}} .king-liquid-glass__button' => 'border-color: {{VALUE}};',
970 ],
971 ]
972 );
973
974 $this->end_controls_tab();
975
976 $this->start_controls_tab(
977 'kng_button_tab_hover',
978 [
979 'label' => esc_html__('Hover', 'king-addons'),
980 ]
981 );
982
983 $this->add_control(
984 'kng_button_text_color_hover',
985 [
986 'label' => esc_html__('Text Color', 'king-addons'),
987 'type' => Controls_Manager::COLOR,
988 'selectors' => [
989 '{{WRAPPER}} .king-liquid-glass__button:hover' => 'color: {{VALUE}};',
990 ],
991 ]
992 );
993
994 $this->add_control(
995 'kng_button_background_hover',
996 [
997 'label' => esc_html__('Background', 'king-addons'),
998 'type' => Controls_Manager::COLOR,
999 'selectors' => [
1000 '{{WRAPPER}} .king-liquid-glass__button:hover' => 'background-color: {{VALUE}};',
1001 ],
1002 ]
1003 );
1004
1005 $this->add_control(
1006 'kng_button_border_color_hover',
1007 [
1008 'label' => esc_html__('Border Color', 'king-addons'),
1009 'type' => Controls_Manager::COLOR,
1010 'selectors' => [
1011 '{{WRAPPER}} .king-liquid-glass__button:hover' => 'border-color: {{VALUE}};',
1012 ],
1013 ]
1014 );
1015
1016 $this->end_controls_tab();
1017
1018 $this->end_controls_tabs();
1019
1020 $this->add_control(
1021 'kng_button_border_width',
1022 [
1023 'label' => esc_html__('Border Width', 'king-addons'),
1024 'type' => Controls_Manager::SLIDER,
1025 'size_units' => ['px'],
1026 'range' => [
1027 'px' => [
1028 'min' => 0,
1029 'max' => 6,
1030 ],
1031 ],
1032 'selectors' => [
1033 '{{WRAPPER}} .king-liquid-glass__button' => 'border-width: {{SIZE}}{{UNIT}};',
1034 ],
1035 ]
1036 );
1037
1038 $this->add_control(
1039 'kng_button_radius',
1040 [
1041 'label' => esc_html__('Border Radius', 'king-addons'),
1042 'type' => Controls_Manager::SLIDER,
1043 'size_units' => ['px', '%'],
1044 'range' => [
1045 'px' => [
1046 'min' => 0,
1047 'max' => 100,
1048 ],
1049 '%' => [
1050 'min' => 0,
1051 'max' => 100,
1052 ],
1053 ],
1054 'selectors' => [
1055 '{{WRAPPER}} .king-liquid-glass__button' => 'border-radius: {{SIZE}}{{UNIT}};',
1056 ],
1057 ]
1058 );
1059
1060 $this->add_responsive_control(
1061 'kng_button_padding',
1062 [
1063 'label' => esc_html__('Padding', 'king-addons'),
1064 'type' => Controls_Manager::DIMENSIONS,
1065 'size_units' => ['px', 'em'],
1066 'selectors' => [
1067 '{{WRAPPER}} .king-liquid-glass__button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1068 ],
1069 ]
1070 );
1071
1072 $this->end_controls_section();
1073 }
1074
1075 protected function register_pro_controls(): void
1076 {
1077 $is_pro = $this->is_pro_enabled();
1078 $pro_class = $this->get_pro_control_class();
1079
1080 $this->start_controls_section(
1081 'kng_tilt_section',
1082 [
1083 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Interactive Tilt', 'king-addons'),
1084 'tab' => Controls_Manager::TAB_CONTENT,
1085 ]
1086 );
1087
1088 $this->add_control(
1089 'kng_enable_tilt',
1090 [
1091 'label' => $is_pro ? esc_html__('Enable Tilt', 'king-addons') : sprintf(__('Enable Tilt %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
1092 'type' => Controls_Manager::SWITCHER,
1093 'return_value' => 'yes',
1094 'default' => '',
1095 'classes' => $pro_class,
1096 'render_type' => 'template',
1097 ]
1098 );
1099
1100 $this->add_control(
1101 'kng_tilt_input',
1102 [
1103 'label' => esc_html__('Input Source', 'king-addons'),
1104 'type' => Controls_Manager::SELECT,
1105 'default' => 'pointer',
1106 'options' => [
1107 'pointer' => esc_html__('Pointer', 'king-addons'),
1108 'orientation' => esc_html__('Device Orientation', 'king-addons'),
1109 ],
1110 'condition' => [
1111 'kng_enable_tilt' => 'yes',
1112 ],
1113 'classes' => $pro_class,
1114 'render_type' => 'template',
1115 ]
1116 );
1117
1118 $this->add_control(
1119 'kng_tilt_max',
1120 [
1121 'label' => esc_html__('Max Tilt Angle', 'king-addons'),
1122 'type' => Controls_Manager::SLIDER,
1123 'size_units' => ['custom'],
1124 'range' => [
1125 'custom' => [
1126 'min' => 0,
1127 'max' => 12,
1128 ],
1129 ],
1130 'default' => [
1131 'size' => 8,
1132 ],
1133 'condition' => [
1134 'kng_enable_tilt' => 'yes',
1135 ],
1136 'classes' => $pro_class,
1137 'render_type' => 'template',
1138 ]
1139 );
1140
1141 $this->add_control(
1142 'kng_tilt_smoothing',
1143 [
1144 'label' => esc_html__('Tilt Smoothing', 'king-addons'),
1145 'type' => Controls_Manager::SLIDER,
1146 'size_units' => ['custom'],
1147 'range' => [
1148 'custom' => [
1149 'min' => 0.02,
1150 'max' => 0.5,
1151 'step' => 0.01,
1152 ],
1153 ],
1154 'default' => [
1155 'size' => 0.12,
1156 ],
1157 'condition' => [
1158 'kng_enable_tilt' => 'yes',
1159 ],
1160 'classes' => $pro_class,
1161 'render_type' => 'template',
1162 ]
1163 );
1164
1165 $this->add_control(
1166 'kng_glare_enable',
1167 [
1168 'label' => esc_html__('Glare Highlight', 'king-addons'),
1169 'type' => Controls_Manager::SWITCHER,
1170 'return_value' => 'yes',
1171 'default' => '',
1172 'condition' => [
1173 'kng_enable_tilt' => 'yes',
1174 ],
1175 'classes' => $pro_class,
1176 'render_type' => 'template',
1177 ]
1178 );
1179
1180 $this->add_control(
1181 'kng_glare_intensity',
1182 [
1183 'label' => esc_html__('Glare Intensity', 'king-addons'),
1184 'type' => Controls_Manager::SLIDER,
1185 'size_units' => ['custom'],
1186 'range' => [
1187 'custom' => [
1188 'min' => 0,
1189 'max' => 0.8,
1190 'step' => 0.01,
1191 ],
1192 ],
1193 'default' => [
1194 'size' => 0.35,
1195 ],
1196 'condition' => [
1197 'kng_enable_tilt' => 'yes',
1198 'kng_glare_enable' => 'yes',
1199 ],
1200 'classes' => $pro_class,
1201 'render_type' => 'template',
1202 ]
1203 );
1204
1205 $this->add_control(
1206 'kng_glare_size',
1207 [
1208 'label' => esc_html__('Glare Size', 'king-addons'),
1209 'type' => Controls_Manager::SLIDER,
1210 'size_units' => ['%'],
1211 'range' => [
1212 '%' => [
1213 'min' => 20,
1214 'max' => 120,
1215 ],
1216 ],
1217 'default' => [
1218 'size' => 65,
1219 'unit' => '%',
1220 ],
1221 'condition' => [
1222 'kng_enable_tilt' => 'yes',
1223 'kng_glare_enable' => 'yes',
1224 ],
1225 'classes' => $pro_class,
1226 'render_type' => 'template',
1227 ]
1228 );
1229
1230 $this->add_control(
1231 'kng_glare_blend',
1232 [
1233 'label' => esc_html__('Glare Blend Mode', 'king-addons'),
1234 'type' => Controls_Manager::SELECT,
1235 'default' => 'screen',
1236 'options' => [
1237 'normal' => esc_html__('Normal', 'king-addons'),
1238 'screen' => esc_html__('Screen', 'king-addons'),
1239 'overlay' => esc_html__('Overlay', 'king-addons'),
1240 ],
1241 'condition' => [
1242 'kng_enable_tilt' => 'yes',
1243 'kng_glare_enable' => 'yes',
1244 ],
1245 'classes' => $pro_class,
1246 'render_type' => 'template',
1247 ]
1248 );
1249
1250 $this->add_control(
1251 'kng_hover_lift',
1252 [
1253 'label' => esc_html__('Hover Lift', 'king-addons'),
1254 'type' => Controls_Manager::SWITCHER,
1255 'return_value' => 'yes',
1256 'default' => '',
1257 'condition' => [
1258 'kng_enable_tilt' => 'yes',
1259 ],
1260 'classes' => $pro_class,
1261 'render_type' => 'template',
1262 ]
1263 );
1264
1265 $this->add_control(
1266 'kng_hover_lift_distance',
1267 [
1268 'label' => esc_html__('Lift Distance', 'king-addons'),
1269 'type' => Controls_Manager::SLIDER,
1270 'size_units' => ['px'],
1271 'range' => [
1272 'px' => [
1273 'min' => 0,
1274 'max' => 30,
1275 ],
1276 ],
1277 'default' => [
1278 'size' => 10,
1279 'unit' => 'px',
1280 ],
1281 'condition' => [
1282 'kng_enable_tilt' => 'yes',
1283 'kng_hover_lift' => 'yes',
1284 ],
1285 'classes' => $pro_class,
1286 'render_type' => 'template',
1287 ]
1288 );
1289
1290 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'liquid-glass-cards', 'kng_enable_tilt', ['yes']);
1291
1292 $this->end_controls_section();
1293
1294 $this->start_controls_section(
1295 'kng_parallax_section',
1296 [
1297 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Parallax Layers', 'king-addons'),
1298 'tab' => Controls_Manager::TAB_CONTENT,
1299 ]
1300 );
1301
1302 $this->add_control(
1303 'kng_enable_parallax',
1304 [
1305 'label' => $is_pro ? esc_html__('Enable Parallax', 'king-addons') : sprintf(__('Enable Parallax %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
1306 'type' => Controls_Manager::SWITCHER,
1307 'return_value' => 'yes',
1308 'default' => '',
1309 'classes' => $pro_class,
1310 'render_type' => 'template',
1311 ]
1312 );
1313
1314 $this->add_control(
1315 'kng_parallax_mode',
1316 [
1317 'label' => esc_html__('Parallax Mode', 'king-addons'),
1318 'type' => Controls_Manager::SELECT,
1319 'default' => 'pointer',
1320 'options' => [
1321 'pointer' => esc_html__('Pointer', 'king-addons'),
1322 'scroll' => esc_html__('Scroll', 'king-addons'),
1323 ],
1324 'condition' => [
1325 'kng_enable_parallax' => 'yes',
1326 ],
1327 'classes' => $pro_class,
1328 'render_type' => 'template',
1329 ]
1330 );
1331
1332 $this->add_control(
1333 'kng_parallax_image_depth',
1334 [
1335 'label' => esc_html__('Image Layer Depth', 'king-addons'),
1336 'type' => Controls_Manager::SLIDER,
1337 'size_units' => ['px'],
1338 'range' => [
1339 'px' => [
1340 'min' => -30,
1341 'max' => 30,
1342 ],
1343 ],
1344 'default' => [
1345 'size' => 12,
1346 'unit' => 'px',
1347 ],
1348 'condition' => [
1349 'kng_enable_parallax' => 'yes',
1350 ],
1351 'classes' => $pro_class,
1352 'render_type' => 'template',
1353 ]
1354 );
1355
1356 $layer_repeater = new Repeater();
1357
1358 $layer_repeater->add_control(
1359 'kng_layer_type',
1360 [
1361 'label' => esc_html__('Layer Type', 'king-addons'),
1362 'type' => Controls_Manager::SELECT,
1363 'default' => 'gradient',
1364 'options' => [
1365 'image' => esc_html__('Image', 'king-addons'),
1366 'gradient' => esc_html__('Gradient', 'king-addons'),
1367 'highlight' => esc_html__('Highlight', 'king-addons'),
1368 ],
1369 ]
1370 );
1371
1372 $layer_repeater->add_control(
1373 'kng_layer_image',
1374 [
1375 'label' => esc_html__('Layer Image', 'king-addons'),
1376 'type' => Controls_Manager::MEDIA,
1377 'condition' => [
1378 'kng_layer_type' => 'image',
1379 ],
1380 ]
1381 );
1382
1383 $layer_repeater->add_control(
1384 'kng_layer_color',
1385 [
1386 'label' => esc_html__('Layer Color', 'king-addons'),
1387 'type' => Controls_Manager::COLOR,
1388 'condition' => [
1389 'kng_layer_type!' => 'image',
1390 ],
1391 ]
1392 );
1393
1394 $layer_repeater->add_control(
1395 'kng_layer_color_end',
1396 [
1397 'label' => esc_html__('Secondary Color', 'king-addons'),
1398 'type' => Controls_Manager::COLOR,
1399 'condition' => [
1400 'kng_layer_type' => 'gradient',
1401 ],
1402 ]
1403 );
1404
1405 $layer_repeater->add_control(
1406 'kng_layer_depth',
1407 [
1408 'label' => esc_html__('Depth', 'king-addons'),
1409 'type' => Controls_Manager::SLIDER,
1410 'size_units' => ['px'],
1411 'range' => [
1412 'px' => [
1413 'min' => -30,
1414 'max' => 30,
1415 ],
1416 ],
1417 'default' => [
1418 'size' => 14,
1419 'unit' => 'px',
1420 ],
1421 ]
1422 );
1423
1424 $layer_repeater->add_control(
1425 'kng_layer_opacity',
1426 [
1427 'label' => esc_html__('Opacity', 'king-addons'),
1428 'type' => Controls_Manager::SLIDER,
1429 'size_units' => ['custom'],
1430 'range' => [
1431 'custom' => [
1432 'min' => 0,
1433 'max' => 1,
1434 'step' => 0.01,
1435 ],
1436 ],
1437 'default' => [
1438 'size' => 0.35,
1439 ],
1440 ]
1441 );
1442
1443 $layer_repeater->add_control(
1444 'kng_layer_blur',
1445 [
1446 'label' => esc_html__('Blur', 'king-addons'),
1447 'type' => Controls_Manager::SLIDER,
1448 'size_units' => ['px'],
1449 'range' => [
1450 'px' => [
1451 'min' => 0,
1452 'max' => 30,
1453 ],
1454 ],
1455 ]
1456 );
1457
1458 $layer_repeater->add_control(
1459 'kng_layer_blend',
1460 [
1461 'label' => esc_html__('Blend Mode', 'king-addons'),
1462 'type' => Controls_Manager::SELECT,
1463 'default' => 'normal',
1464 'options' => [
1465 'normal' => esc_html__('Normal', 'king-addons'),
1466 'screen' => esc_html__('Screen', 'king-addons'),
1467 'overlay' => esc_html__('Overlay', 'king-addons'),
1468 'soft-light' => esc_html__('Soft Light', 'king-addons'),
1469 ],
1470 ]
1471 );
1472
1473 $this->add_control(
1474 'kng_parallax_layers',
1475 [
1476 'label' => esc_html__('Layers', 'king-addons'),
1477 'type' => Controls_Manager::REPEATER,
1478 'fields' => $layer_repeater->get_controls(),
1479 'title_field' => '{{ kng_layer_type }}',
1480 'default' => [
1481 [
1482 'kng_layer_type' => 'gradient',
1483 'kng_layer_color' => 'rgba(255,255,255,0.6)',
1484 'kng_layer_color_end' => 'rgba(255,255,255,0)',
1485 'kng_layer_depth' => [
1486 'size' => 10,
1487 'unit' => 'px',
1488 ],
1489 ],
1490 ],
1491 'condition' => [
1492 'kng_enable_parallax' => 'yes',
1493 ],
1494 'classes' => $pro_class,
1495 ]
1496 );
1497
1498 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'liquid-glass-cards', 'kng_enable_parallax', ['yes']);
1499
1500 $this->end_controls_section();
1501
1502 $this->start_controls_section(
1503 'kng_performance_section',
1504 [
1505 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Adaptive Performance', 'king-addons'),
1506 'tab' => Controls_Manager::TAB_CONTENT,
1507 ]
1508 );
1509
1510 $this->add_control(
1511 'kng_performance_mode',
1512 [
1513 'label' => $is_pro ? esc_html__('Performance Mode', 'king-addons') : sprintf(__('Performance Mode %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
1514 'type' => Controls_Manager::SELECT,
1515 'default' => 'auto',
1516 'options' => [
1517 'auto' => esc_html__('Auto', 'king-addons'),
1518 'quality' => esc_html__('Quality', 'king-addons'),
1519 'balanced' => esc_html__('Balanced', 'king-addons'),
1520 'performance' => esc_html__('Performance', 'king-addons'),
1521 ],
1522 'classes' => $pro_class,
1523 'render_type' => 'template',
1524 ]
1525 );
1526
1527 $this->end_controls_section();
1528 }
1529
1530 protected function register_pro_notice_controls(): void
1531 {
1532 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'liquid-glass-cards', [
1533 'Add interactive depth with pointer-based tilt and dynamic highlights.',
1534 'Layered parallax creates premium dimensionality without heavy libraries.',
1535 'Auto-adjust effects for smooth rendering on any device.',
1536 ]);
1537 }
1538
1539 protected function render_output(array $settings): void
1540 {
1541 $cards = $settings['kng_cards'] ?? [];
1542 if (empty($cards)) {
1543 return;
1544 }
1545
1546 $is_editor = class_exists(Plugin::class) && Plugin::$instance->editor->is_edit_mode();
1547 $is_pro = $this->is_pro_enabled();
1548 $wrapper_classes = $this->get_wrapper_classes($settings, $is_pro);
1549 $wrapper_style = $this->get_wrapper_style($settings);
1550 $data_attributes = $this->get_data_attributes($settings, $cards, $is_pro);
1551
1552 if ($is_pro && $this->should_enqueue_script($settings)) {
1553 wp_enqueue_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-liquid-glass-cards-script');
1554 }
1555
1556 ?>
1557 <div class="<?php echo esc_attr(implode(' ', $wrapper_classes)); ?>"<?php echo $wrapper_style; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?><?php echo $data_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1558 <?php if ($is_editor && count($cards) > 12 && $is_pro && $this->should_enqueue_script($settings)) : ?>
1559 <div class="king-liquid-glass__notice elementor-alert elementor-alert-warning">
1560 <?php echo esc_html__('Tip: For best performance, keep card count under 12 when effects are enabled.', 'king-addons'); ?>
1561 </div>
1562 <?php endif; ?>
1563 <div class="king-liquid-glass__grid">
1564 <?php foreach ($cards as $index => $card) : ?>
1565 <?php $this->render_card($settings, $card, $index, $is_pro); ?>
1566 <?php endforeach; ?>
1567 </div>
1568 </div>
1569 <?php
1570 }
1571
1572 protected function render_card(array $settings, array $card, int $index, bool $is_pro): void
1573 {
1574 $title = $card['kng_card_title'] ?? '';
1575 $subtitle = $card['kng_card_subtitle'] ?? '';
1576 $description = $card['kng_card_description'] ?? '';
1577 $badge = $card['kng_card_badge'] ?? '';
1578 $icon = $card['kng_card_icon'] ?? [];
1579 $button_text = $card['kng_card_button_text'] ?? '';
1580 $button_link = $card['kng_card_button_link'] ?? [];
1581 $link_mode = $card['kng_card_link_mode'] ?? 'button';
1582
1583 $show_badge = ($card['kng_card_show_badge'] ?? 'yes') === 'yes';
1584 $show_icon = ($card['kng_card_show_icon'] ?? 'yes') === 'yes';
1585 $show_button = ($card['kng_card_show_button'] ?? 'yes') === 'yes';
1586
1587 $image_display = $card['kng_card_image_display'] ?? 'layer';
1588 $image_html = $image_display === 'thumb' ? $this->get_card_image_html($card) : '';
1589 $image_src = $image_display === 'layer' ? $this->get_card_image_src($settings, $card) : '';
1590
1591 $card_classes = ['king-liquid-glass__card'];
1592 if (!empty($card['_id'])) {
1593 $card_classes[] = 'elementor-repeater-item-' . sanitize_html_class((string) $card['_id']);
1594 }
1595
1596 $title_tag = $this->get_card_title_tag($settings);
1597 $link_attributes = $this->get_link_attributes($button_link);
1598 $card_link_enabled = $link_mode === 'card' && !empty($button_link['url']);
1599 $button_link_enabled = $link_mode === 'button' && !empty($button_link['url']);
1600
1601 $image_depth = $this->get_parallax_image_depth($settings, $is_pro);
1602 $parallax_layers = $this->get_parallax_layers($settings, $is_pro);
1603
1604 ?>
1605 <article class="<?php echo esc_attr(implode(' ', $card_classes)); ?>">
1606 <div class="king-liquid-glass__layers">
1607 <div class="king-liquid-glass__layer king-liquid-glass__layer--bg"></div>
1608 <?php if ($image_src) : ?>
1609 <div class="king-liquid-glass__layer king-liquid-glass__layer--image"<?php echo $image_depth !== null ? ' data-depth="' . esc_attr((string) $image_depth) . '"' : ''; ?> style="background-image: url('<?php echo esc_url($image_src); ?>');"></div>
1610 <?php endif; ?>
1611 <?php if (!empty($parallax_layers)) : ?>
1612 <?php foreach ($parallax_layers as $layer) : ?>
1613 <?php $this->render_parallax_layer($layer); ?>
1614 <?php endforeach; ?>
1615 <?php endif; ?>
1616 <div class="king-liquid-glass__layer king-liquid-glass__layer--noise"></div>
1617 <div class="king-liquid-glass__layer king-liquid-glass__layer--highlight"></div>
1618 </div>
1619 <div class="king-liquid-glass__content">
1620 <?php if ($show_badge && !empty($badge)) : ?>
1621 <div class="king-liquid-glass__badge"><?php echo esc_html($badge); ?></div>
1622 <?php endif; ?>
1623 <?php if ($show_icon && !empty($icon['value'])) : ?>
1624 <div class="king-liquid-glass__icon">
1625 <?php Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']); ?>
1626 </div>
1627 <?php endif; ?>
1628 <?php if (!empty($image_html)) : ?>
1629 <div class="king-liquid-glass__media">
1630 <?php echo $image_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
1631 </div>
1632 <?php endif; ?>
1633 <?php if (!empty($title)) : ?>
1634 <<?php echo tag_escape($title_tag); ?> class="king-liquid-glass__title"><?php echo esc_html($title); ?></<?php echo tag_escape($title_tag); ?>>
1635 <?php endif; ?>
1636 <?php if (!empty($subtitle)) : ?>
1637 <div class="king-liquid-glass__subtitle"><?php echo esc_html($subtitle); ?></div>
1638 <?php endif; ?>
1639 <?php if (!empty($description)) : ?>
1640 <div class="king-liquid-glass__description"><?php echo wp_kses_post($description); ?></div>
1641 <?php endif; ?>
1642 <?php if ($show_button && !empty($button_text)) : ?>
1643 <?php $this->render_button($button_text, $link_attributes, $button_link_enabled); ?>
1644 <?php endif; ?>
1645 </div>
1646 <?php if ($card_link_enabled) : ?>
1647 <a class="king-liquid-glass__card-link"<?php echo $link_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> aria-label="<?php echo esc_attr($title ?: $button_text ?: esc_html__('Open card', 'king-addons')); ?>"></a>
1648 <?php endif; ?>
1649 </article>
1650 <?php
1651 }
1652
1653 protected function render_button(string $text, string $link_attributes, bool $is_link): void
1654 {
1655 if ($is_link) {
1656 ?>
1657 <a class="king-liquid-glass__button"<?php echo $link_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
1658 <?php echo esc_html($text); ?>
1659 </a>
1660 <?php
1661 return;
1662 }
1663 ?>
1664 <span class="king-liquid-glass__button is-static"><?php echo esc_html($text); ?></span>
1665 <?php
1666 }
1667
1668 protected function render_parallax_layer(array $layer): void
1669 {
1670 $layer_type = $layer['kng_layer_type'] ?? 'gradient';
1671 $depth = $layer['kng_layer_depth']['size'] ?? 0;
1672 $opacity = $layer['kng_layer_opacity']['size'] ?? '';
1673 $blur = $layer['kng_layer_blur']['size'] ?? '';
1674 $blend = $layer['kng_layer_blend'] ?? 'normal';
1675
1676 $style_parts = [];
1677 if ($opacity !== '') {
1678 $style_parts[] = 'opacity:' . (float) $opacity . ';';
1679 }
1680 if ($blur !== '') {
1681 $style_parts[] = 'filter: blur(' . (float) $blur . 'px);';
1682 }
1683 if (!empty($blend)) {
1684 $style_parts[] = 'mix-blend-mode:' . esc_attr((string) $blend) . ';';
1685 }
1686
1687 if ($layer_type === 'image') {
1688 $image = $layer['kng_layer_image']['url'] ?? '';
1689 if ($image) {
1690 $style_parts[] = 'background-image:url(' . esc_url($image) . ');';
1691 }
1692 } else {
1693 $color = $layer['kng_layer_color'] ?? '';
1694 if ($color === '') {
1695 $color = 'rgba(255,255,255,0.4)';
1696 }
1697 $secondary = $layer['kng_layer_color_end'] ?? '';
1698 if ($secondary === '') {
1699 $secondary = 'rgba(255,255,255,0)';
1700 }
1701 if ($layer_type === 'highlight') {
1702 $style_parts[] = 'background-image: radial-gradient(circle at 20% 20%, ' . esc_attr($color) . ' 0%, rgba(255,255,255,0) 65%);';
1703 } else {
1704 $style_parts[] = 'background-image: radial-gradient(circle at 30% 20%, ' . esc_attr($color) . ' 0%, ' . esc_attr($secondary) . ' 70%);';
1705 }
1706 }
1707
1708 $style_attribute = '';
1709 if (!empty($style_parts)) {
1710 $style_attribute = ' style="' . esc_attr(implode(' ', $style_parts)) . '"';
1711 }
1712
1713 $depth_attribute = $depth !== '' ? ' data-depth="' . esc_attr((string) $depth) . '"' : '';
1714
1715 echo '<div class="king-liquid-glass__layer king-liquid-glass__layer--parallax"' . $depth_attribute . $style_attribute . '></div>';
1716 }
1717
1718 protected function get_wrapper_classes(array $settings, bool $is_pro): array
1719 {
1720 $preset = $settings['kng_preset'] ?? 'clear';
1721 $align = $settings['kng_content_alignment'] ?? 'left';
1722 $shadow = $settings['kng_shadow_style'] ?? 'soft';
1723 $tint = $settings['kng_tint_mode'] ?? 'auto';
1724 $highlight = $settings['kng_highlight_position'] ?? 'top-left';
1725 $noise = $settings['kng_noise_mode'] ?? 'on';
1726
1727 $classes = [
1728 'king-liquid-glass',
1729 'king-liquid-glass--preset-' . sanitize_html_class((string) $preset),
1730 'king-liquid-glass--align-' . sanitize_html_class((string) $align),
1731 'king-liquid-glass--shadow-' . sanitize_html_class((string) $shadow),
1732 'king-liquid-glass--tint-' . sanitize_html_class((string) $tint),
1733 'king-liquid-glass--highlight-' . sanitize_html_class((string) $highlight),
1734 'king-liquid-glass--noise-' . sanitize_html_class((string) $noise),
1735 ];
1736
1737 if (($settings['kng_equal_height'] ?? '') === 'yes') {
1738 $classes[] = 'king-liquid-glass--equal-height';
1739 }
1740
1741 if ($is_pro) {
1742 $classes[] = 'king-liquid-glass--pro';
1743 }
1744
1745 return array_filter($classes);
1746 }
1747
1748 protected function get_wrapper_style(array $settings): string
1749 {
1750 $style_parts = [];
1751
1752 if (isset($settings['kng_blur']['size']) && $settings['kng_blur']['size'] !== '') {
1753 $style_parts[] = '--kng-liquid-blur:' . (float) $settings['kng_blur']['size'] . ($settings['kng_blur']['unit'] ?? 'px') . ';';
1754 }
1755
1756 if (($settings['kng_tint_mode'] ?? '') === 'custom' && !empty($settings['kng_tint_color'])) {
1757 $style_parts[] = '--kng-liquid-tint:' . $settings['kng_tint_color'] . ';';
1758 }
1759
1760 if (isset($settings['kng_border_width']['size']) && $settings['kng_border_width']['size'] !== '') {
1761 $style_parts[] = '--kng-liquid-border-width:' . (float) $settings['kng_border_width']['size'] . ($settings['kng_border_width']['unit'] ?? 'px') . ';';
1762 }
1763
1764 if (!empty($settings['kng_border_color'])) {
1765 $style_parts[] = '--kng-liquid-border-color:' . $settings['kng_border_color'] . ';';
1766 }
1767
1768 if (isset($settings['kng_noise_opacity']['size']) && $settings['kng_noise_opacity']['size'] !== '') {
1769 $style_parts[] = '--kng-liquid-noise-opacity:' . (float) $settings['kng_noise_opacity']['size'] . ';';
1770 }
1771
1772 if (isset($settings['kng_noise_scale']['size']) && $settings['kng_noise_scale']['size'] !== '') {
1773 $style_parts[] = '--kng-liquid-noise-scale:' . (float) $settings['kng_noise_scale']['size'] . ($settings['kng_noise_scale']['unit'] ?? 'px') . ';';
1774 }
1775
1776 if (isset($settings['kng_highlight_intensity']['size']) && $settings['kng_highlight_intensity']['size'] !== '') {
1777 $style_parts[] = '--kng-liquid-highlight-opacity:' . (float) $settings['kng_highlight_intensity']['size'] . ';';
1778 }
1779
1780 if (!empty($settings['kng_highlight_color'])) {
1781 $style_parts[] = '--kng-liquid-highlight-color:' . $settings['kng_highlight_color'] . ';';
1782 }
1783
1784 if (isset($settings['kng_image_opacity']['size']) && $settings['kng_image_opacity']['size'] !== '') {
1785 $style_parts[] = '--kng-liquid-image-opacity:' . (float) $settings['kng_image_opacity']['size'] . ';';
1786 }
1787
1788 if (!empty($settings['kng_image_blend'])) {
1789 $style_parts[] = '--kng-liquid-image-blend:' . $settings['kng_image_blend'] . ';';
1790 }
1791
1792 if (!empty($style_parts)) {
1793 return ' style="' . esc_attr(implode(' ', $style_parts)) . '"';
1794 }
1795
1796 return '';
1797 }
1798
1799 protected function get_data_attributes(array $settings, array $cards, bool $is_pro): string
1800 {
1801 if (!$is_pro) {
1802 return '';
1803 }
1804
1805 $tilt_enabled = ($settings['kng_enable_tilt'] ?? '') === 'yes';
1806 $parallax_enabled = ($settings['kng_enable_parallax'] ?? '') === 'yes';
1807
1808 if (!$tilt_enabled && !$parallax_enabled) {
1809 return '';
1810 }
1811
1812 $tilt = [
1813 'enabled' => $tilt_enabled,
1814 'input' => $settings['kng_tilt_input'] ?? 'pointer',
1815 'max' => $settings['kng_tilt_max']['size'] ?? 8,
1816 'smoothing' => $settings['kng_tilt_smoothing']['size'] ?? 0.12,
1817 'glare' => [
1818 'enabled' => ($settings['kng_glare_enable'] ?? '') === 'yes',
1819 'intensity' => $settings['kng_glare_intensity']['size'] ?? 0.35,
1820 'size' => $settings['kng_glare_size']['size'] ?? 65,
1821 'blend' => $settings['kng_glare_blend'] ?? 'screen',
1822 ],
1823 'lift' => [
1824 'enabled' => ($settings['kng_hover_lift'] ?? '') === 'yes',
1825 'distance' => $settings['kng_hover_lift_distance']['size'] ?? 10,
1826 ],
1827 ];
1828
1829 $parallax = [
1830 'enabled' => $parallax_enabled,
1831 'mode' => $settings['kng_parallax_mode'] ?? 'pointer',
1832 ];
1833
1834 $performance = [
1835 'mode' => $settings['kng_performance_mode'] ?? 'auto',
1836 ];
1837
1838 $payload = [
1839 'pro' => true,
1840 'cardCount' => count($cards),
1841 'tilt' => $tilt,
1842 'parallax' => $parallax,
1843 'performance' => $performance,
1844 ];
1845
1846 return ' data-settings="' . esc_attr(wp_json_encode($payload)) . '"';
1847 }
1848
1849 protected function get_link_attributes(array $link): string
1850 {
1851 $url = $link['url'] ?? '';
1852 if (empty($url)) {
1853 return '';
1854 }
1855
1856 $attributes = [];
1857 $attributes[] = 'href="' . esc_url($url) . '"';
1858
1859 if (!empty($link['is_external'])) {
1860 $attributes[] = 'target="_blank"';
1861 }
1862
1863 $rel = [];
1864 if (!empty($link['nofollow'])) {
1865 $rel[] = 'nofollow';
1866 }
1867 if (!empty($link['is_external'])) {
1868 $rel[] = 'noopener';
1869 $rel[] = 'noreferrer';
1870 }
1871
1872 if (!empty($rel)) {
1873 $attributes[] = 'rel="' . esc_attr(implode(' ', array_unique($rel))) . '"';
1874 }
1875
1876 return ' ' . implode(' ', $attributes);
1877 }
1878
1879 protected function get_card_image_html(array $card): string
1880 {
1881 if (empty($card['kng_card_image']['id']) && empty($card['kng_card_image']['url'])) {
1882 return '';
1883 }
1884
1885 $image_html = Group_Control_Image_Size::get_attachment_image_html($card, 'kng_card_image');
1886
1887 if (!empty($image_html)) {
1888 return $image_html;
1889 }
1890
1891 return '<img src="' . esc_url(Utils::get_placeholder_image_src()) . '" alt="' . esc_attr($card['kng_card_title'] ?? '') . '"/>';
1892 }
1893
1894 protected function get_card_image_src(array $settings, array $card): string
1895 {
1896 $image = $card['kng_card_image'] ?? [];
1897 if (empty($image['id']) && empty($image['url'])) {
1898 return '';
1899 }
1900
1901 if (!empty($image['id'])) {
1902 $src = Group_Control_Image_Size::get_attachment_image_src($image['id'], 'kng_card_image', $settings);
1903 if ($src) {
1904 return $src;
1905 }
1906 }
1907
1908 return $image['url'] ?? '';
1909 }
1910
1911 protected function get_parallax_layers(array $settings, bool $is_pro): array
1912 {
1913 if (!$is_pro) {
1914 return [];
1915 }
1916
1917 if (($settings['kng_enable_parallax'] ?? '') !== 'yes') {
1918 return [];
1919 }
1920
1921 $layers = $settings['kng_parallax_layers'] ?? [];
1922 if (!is_array($layers)) {
1923 return [];
1924 }
1925
1926 return array_slice($layers, 0, 4);
1927 }
1928
1929 protected function get_parallax_image_depth(array $settings, bool $is_pro): ?float
1930 {
1931 if (!$is_pro || ($settings['kng_enable_parallax'] ?? '') !== 'yes') {
1932 return null;
1933 }
1934
1935 if (!isset($settings['kng_parallax_image_depth']['size'])) {
1936 return null;
1937 }
1938
1939 return (float) $settings['kng_parallax_image_depth']['size'];
1940 }
1941
1942 protected function get_card_title_tag(array $settings): string
1943 {
1944 $tag = $settings['kng_title_tag'] ?? 'h3';
1945 $allowed = ['h2', 'h3', 'h4', 'div'];
1946
1947 if (!in_array($tag, $allowed, true)) {
1948 return 'h3';
1949 }
1950
1951 return $tag;
1952 }
1953
1954 protected function get_default_cards(): array
1955 {
1956 $placeholder = Utils::get_placeholder_image_src();
1957
1958 return [
1959 [
1960 'kng_card_title' => esc_html__('Liquid clarity', 'king-addons'),
1961 'kng_card_subtitle' => esc_html__('Preset one', 'king-addons'),
1962 'kng_card_description' => esc_html__('A clean glass card ready for hero sections and feature grids.', 'king-addons'),
1963 'kng_card_badge' => esc_html__('Preset 1', 'king-addons'),
1964 'kng_card_button_text' => esc_html__('Explore', 'king-addons'),
1965 'kng_card_image' => ['url' => $placeholder],
1966 ],
1967 [
1968 'kng_card_title' => esc_html__('Frosted depth', 'king-addons'),
1969 'kng_card_subtitle' => esc_html__('Preset two', 'king-addons'),
1970 'kng_card_description' => esc_html__('Softer blur and noise for layered marketing content.', 'king-addons'),
1971 'kng_card_badge' => esc_html__('Preset 2', 'king-addons'),
1972 'kng_card_button_text' => esc_html__('Details', 'king-addons'),
1973 'kng_card_image' => ['url' => $placeholder],
1974 ],
1975 [
1976 'kng_card_title' => esc_html__('Dark glass', 'king-addons'),
1977 'kng_card_subtitle' => esc_html__('Preset three', 'king-addons'),
1978 'kng_card_description' => esc_html__('Rich dark glass tuned for bold hero backdrops.', 'king-addons'),
1979 'kng_card_badge' => esc_html__('Preset 3', 'king-addons'),
1980 'kng_card_button_text' => esc_html__('See more', 'king-addons'),
1981 'kng_card_image' => ['url' => $placeholder],
1982 ],
1983 ];
1984 }
1985
1986 protected function is_pro_enabled(): bool
1987 {
1988 return function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code__premium_only();
1989 }
1990
1991 protected function should_enqueue_script(array $settings): bool
1992 {
1993 if (!$this->is_pro_enabled()) {
1994 return false;
1995 }
1996
1997 $flags = [
1998 $settings['kng_enable_tilt'] ?? '',
1999 $settings['kng_enable_parallax'] ?? '',
2000 ];
2001
2002 foreach ($flags as $flag) {
2003 if ($flag === 'yes') {
2004 return true;
2005 }
2006 }
2007
2008 return false;
2009 }
2010
2011 protected function get_pro_control_class(string $extra = ''): string
2012 {
2013 if ($this->is_pro_enabled()) {
2014 return $extra;
2015 }
2016
2017 return trim('king-addons-pro-control ' . $extra);
2018 }
2019 }
2020