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

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

997 lines 32.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Content Toggle Widget (Free)
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Background;
12 use Elementor\Group_Control_Border;
13 use Elementor\Group_Control_Box_Shadow;
14 use Elementor\Group_Control_Image_Size;
15 use Elementor\Group_Control_Typography;
16 use Elementor\Icons_Manager;
17 use Elementor\Plugin;
18 use Elementor\Utils;
19 use Elementor\Widget_Base;
20
21 if (!defined('ABSPATH')) {
22 exit;
23 }
24
25 /**
26 * Renders the Content Toggle widget for the free version.
27 */
28 class Content_Toggle extends Widget_Base
29 {
30 /**
31 * Get widget slug.
32 *
33 * @return string
34 */
35 public function get_name(): string
36 {
37 return 'king-addons-content-toggle';
38 }
39
40 /**
41 * Get widget title.
42 *
43 * @return string
44 */
45 public function get_title(): string
46 {
47 return esc_html__('Content Toggle', 'king-addons');
48 }
49
50 /**
51 * Get widget icon CSS classes.
52 *
53 * @return string
54 */
55 public function get_icon(): string
56 {
57 return 'eicon-toggle';
58 }
59
60 /**
61 * Get script dependencies.
62 *
63 * @return array<string>
64 */
65 public function get_script_depends(): array
66 {
67 return [
68 KING_ADDONS_ASSETS_UNIQUE_KEY . '-content-toggle-script',
69 ];
70 }
71
72 /**
73 * Get style dependencies.
74 *
75 * @return array<string>
76 */
77 public function get_style_depends(): array
78 {
79 return [
80 KING_ADDONS_ASSETS_UNIQUE_KEY . '-content-toggle-style',
81 ];
82 }
83
84 /**
85 * Get widget categories.
86 *
87 * @return array<string>
88 */
89 public function get_categories(): array
90 {
91 return ['king-addons'];
92 }
93
94 /**
95 * Get widget keywords.
96 *
97 * @return array<string>
98 */
99 public function get_keywords(): array
100 {
101 return ['toggle', 'switch', 'content', 'tabs', 'king-addons'];
102 }
103
104 public function get_custom_help_url()
105 {
106 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
107 }
108
109 /**
110 * Register widget controls.
111 *
112 * @return void
113 */
114 public function register_controls(): void
115 {
116 $this->register_toggle_controls();
117 $this->register_primary_content_controls();
118 $this->register_secondary_content_controls();
119 $this->register_external_target_controls();
120 $this->register_style_toggle_controls();
121 $this->register_style_content_controls();
122 $this->register_pro_features_notice();
123 }
124
125 /**
126 * Register Pro-only controls placeholder.
127 *
128 * The Pro version overrides this method to add additional controls without
129 * overriding the full `register_controls()` flow.
130 *
131 * @return void
132 */
133 public function register_external_target_controls(): void
134 {
135 // Intentionally empty in Free.
136 }
137
138 /**
139 * Register general toggle controls.
140 *
141 * @return void
142 */
143 public function register_toggle_controls(): void
144 {
145 $this->start_controls_section(
146 'kng_toggle_section',
147 [
148 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Toggle', 'king-addons'),
149 'tab' => Controls_Manager::TAB_CONTENT,
150 ]
151 );
152
153 $this->add_control(
154 'kng_toggle_label_primary',
155 [
156 'label' => esc_html__('Primary Label', 'king-addons'),
157 'type' => Controls_Manager::TEXT,
158 'default' => esc_html__('Primary', 'king-addons'),
159 'placeholder' => esc_html__('Primary', 'king-addons'),
160 ]
161 );
162
163 $this->add_control(
164 'kng_toggle_label_secondary',
165 [
166 'label' => esc_html__('Secondary Label', 'king-addons'),
167 'type' => Controls_Manager::TEXT,
168 'default' => esc_html__('Secondary', 'king-addons'),
169 'placeholder' => esc_html__('Secondary', 'king-addons'),
170 ]
171 );
172
173 $this->add_control(
174 'kng_default_state',
175 [
176 'label' => esc_html__('Default State', 'king-addons'),
177 'type' => Controls_Manager::SELECT,
178 'default' => 'primary',
179 'options' => [
180 'primary' => esc_html__('Primary', 'king-addons'),
181 'secondary' => esc_html__('Secondary', 'king-addons'),
182 ],
183 'description' => esc_html__('Choose which content is visible on load.', 'king-addons'),
184 ]
185 );
186
187 $this->add_responsive_control(
188 'kng_toggle_alignment',
189 [
190 'label' => esc_html__('Alignment', 'king-addons'),
191 'type' => Controls_Manager::CHOOSE,
192 'options' => [
193 'flex-start' => [
194 'title' => esc_html__('Left', 'king-addons'),
195 'icon' => 'eicon-text-align-left',
196 ],
197 'center' => [
198 'title' => esc_html__('Center', 'king-addons'),
199 'icon' => 'eicon-text-align-center',
200 ],
201 'flex-end' => [
202 'title' => esc_html__('Right', 'king-addons'),
203 'icon' => 'eicon-text-align-right',
204 ],
205 ],
206 'default' => 'flex-start',
207 'selectors' => [
208 '{{WRAPPER}} .king-addons-content-toggle__header' => 'justify-content: {{VALUE}};',
209 ],
210 ]
211 );
212
213 $this->add_control(
214 'kng_animation_style',
215 [
216 'label' => esc_html__('Animation', 'king-addons'),
217 'type' => Controls_Manager::SELECT,
218 'default' => 'fade',
219 'options' => [
220 'fade' => esc_html__('Fade', 'king-addons'),
221 ],
222 'description' => esc_html__('Slide animation is available in the Pro version.', 'king-addons'),
223 ]
224 );
225
226 $this->end_controls_section();
227 }
228
229 /**
230 * Register primary content controls.
231 *
232 * @return void
233 */
234 public function register_primary_content_controls(): void
235 {
236 $this->start_controls_section(
237 'kng_primary_section',
238 [
239 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Primary Content', 'king-addons'),
240 'tab' => Controls_Manager::TAB_CONTENT,
241 ]
242 );
243
244 $this->add_control(
245 'kng_primary_source',
246 [
247 'label' => esc_html__('Source', 'king-addons'),
248 'type' => Controls_Manager::SELECT,
249 'default' => 'text',
250 'options' => [
251 'text' => esc_html__('Text', 'king-addons'),
252 'image' => esc_html__('Image', 'king-addons'),
253 ],
254 ]
255 );
256
257 $this->add_control(
258 'kng_primary_content',
259 [
260 'label' => esc_html__('Content', 'king-addons'),
261 'type' => Controls_Manager::WYSIWYG,
262 'default' => esc_html__('Share your primary content here to highlight the most important information first.', 'king-addons'),
263 'condition' => [
264 'kng_primary_source' => 'text',
265 ],
266 ]
267 );
268
269 $this->add_control(
270 'kng_primary_image',
271 [
272 'label' => esc_html__('Image', 'king-addons'),
273 'type' => Controls_Manager::MEDIA,
274 'default' => [
275 'url' => Utils::get_placeholder_image_src(),
276 ],
277 'condition' => [
278 'kng_primary_source' => 'image',
279 ],
280 ]
281 );
282
283 $this->add_group_control(
284 Group_Control_Image_Size::get_type(),
285 [
286 'name' => 'kng_primary_image',
287 'default' => 'large',
288 'condition' => [
289 'kng_primary_source' => 'image',
290 ],
291 ]
292 );
293
294 $this->add_control(
295 'kng_primary_template_notice',
296 [
297 'type' => Controls_Manager::RAW_HTML,
298 'raw' => esc_html__('Loading Elementor templates is available in the Pro version.', 'king-addons'),
299 'content_classes' => 'king-addons-pro-notice',
300 ]
301 );
302
303 $this->end_controls_section();
304 }
305
306 /**
307 * Register secondary content controls.
308 *
309 * @return void
310 */
311 public function register_secondary_content_controls(): void
312 {
313 $this->start_controls_section(
314 'kng_secondary_section',
315 [
316 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Secondary Content', 'king-addons'),
317 'tab' => Controls_Manager::TAB_CONTENT,
318 ]
319 );
320
321 $this->add_control(
322 'kng_secondary_source',
323 [
324 'label' => esc_html__('Source', 'king-addons'),
325 'type' => Controls_Manager::SELECT,
326 'default' => 'text',
327 'options' => [
328 'text' => esc_html__('Text', 'king-addons'),
329 'image' => esc_html__('Image', 'king-addons'),
330 ],
331 ]
332 );
333
334 $this->add_control(
335 'kng_secondary_content',
336 [
337 'label' => esc_html__('Content', 'king-addons'),
338 'type' => Controls_Manager::WYSIWYG,
339 'default' => esc_html__('Use the secondary area for comparison, alternate offers, or supporting details.', 'king-addons'),
340 'condition' => [
341 'kng_secondary_source' => 'text',
342 ],
343 ]
344 );
345
346 $this->add_control(
347 'kng_secondary_image',
348 [
349 'label' => esc_html__('Image', 'king-addons'),
350 'type' => Controls_Manager::MEDIA,
351 'default' => [
352 'url' => Utils::get_placeholder_image_src(),
353 ],
354 'condition' => [
355 'kng_secondary_source' => 'image',
356 ],
357 ]
358 );
359
360 $this->add_group_control(
361 Group_Control_Image_Size::get_type(),
362 [
363 'name' => 'kng_secondary_image',
364 'default' => 'large',
365 'condition' => [
366 'kng_secondary_source' => 'image',
367 ],
368 ]
369 );
370
371 $this->add_control(
372 'kng_secondary_template_notice',
373 [
374 'type' => Controls_Manager::RAW_HTML,
375 'raw' => esc_html__('Loading Elementor templates is available in the Pro version.', 'king-addons'),
376 'content_classes' => 'king-addons-pro-notice',
377 ]
378 );
379
380 $this->end_controls_section();
381 }
382
383 /**
384 * Register toggle style controls.
385 *
386 * @return void
387 */
388 public function register_style_toggle_controls(): void
389 {
390 $this->start_controls_section(
391 'kng_toggle_style_section',
392 [
393 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Toggle', 'king-addons'),
394 'tab' => Controls_Manager::TAB_STYLE,
395 ]
396 );
397
398 $this->add_responsive_control(
399 'kng_toggle_gap',
400 [
401 'label' => esc_html__('Toggle Spacing', 'king-addons'),
402 'type' => Controls_Manager::SLIDER,
403 'size_units' => ['px'],
404 'range' => [
405 'px' => [
406 'min' => 0,
407 'max' => 64,
408 ],
409 ],
410 'selectors' => [
411 '{{WRAPPER}} .king-addons-content-toggle__header' => 'margin-bottom: {{SIZE}}{{UNIT}};',
412 ],
413 ]
414 );
415
416 $this->add_responsive_control(
417 'kng_toggle_width',
418 [
419 'label' => esc_html__('Switch Width', 'king-addons'),
420 'type' => Controls_Manager::SLIDER,
421 'size_units' => ['px'],
422 'range' => [
423 'px' => [
424 'min' => 80,
425 'max' => 200,
426 ],
427 ],
428 'selectors' => [
429 '{{WRAPPER}} .king-addons-content-toggle' => '--kng-toggle-width: {{SIZE}}{{UNIT}};',
430 ],
431 ]
432 );
433
434 $this->add_responsive_control(
435 'kng_toggle_height',
436 [
437 'label' => esc_html__('Switch Height', 'king-addons'),
438 'type' => Controls_Manager::SLIDER,
439 'size_units' => ['px'],
440 'range' => [
441 'px' => [
442 'min' => 28,
443 'max' => 80,
444 ],
445 ],
446 'selectors' => [
447 '{{WRAPPER}} .king-addons-content-toggle' => '--kng-toggle-height: {{SIZE}}{{UNIT}};',
448 ],
449 ]
450 );
451
452 $this->add_control(
453 'kng_track_color',
454 [
455 'label' => esc_html__('Track', 'king-addons'),
456 'type' => Controls_Manager::COLOR,
457 'selectors' => [
458 '{{WRAPPER}} .king-addons-content-toggle' => '--kng-toggle-track: {{VALUE}};',
459 ],
460 ]
461 );
462
463 $this->add_control(
464 'kng_track_active_color',
465 [
466 'label' => esc_html__('Track Active', 'king-addons'),
467 'type' => Controls_Manager::COLOR,
468 'selectors' => [
469 '{{WRAPPER}} .king-addons-content-toggle' => '--kng-toggle-track-active: {{VALUE}};',
470 ],
471 ]
472 );
473
474 $this->add_control(
475 'kng_thumb_color',
476 [
477 'label' => esc_html__('Thumb', 'king-addons'),
478 'type' => Controls_Manager::COLOR,
479 'selectors' => [
480 '{{WRAPPER}} .king-addons-content-toggle' => '--kng-toggle-thumb: {{VALUE}};',
481 ],
482 ]
483 );
484
485 $this->add_group_control(
486 Group_Control_Border::get_type(),
487 [
488 'name' => 'kng_switch_border',
489 'selector' => '{{WRAPPER}} .king-addons-content-toggle__switch',
490 ]
491 );
492
493 $this->add_group_control(
494 Group_Control_Box_Shadow::get_type(),
495 [
496 'name' => 'kng_switch_shadow',
497 'selector' => '{{WRAPPER}} .king-addons-content-toggle__switch',
498 ]
499 );
500
501 $this->add_group_control(
502 Group_Control_Typography::get_type(),
503 [
504 'name' => 'kng_labels_typography',
505 'selector' => '{{WRAPPER}} .king-addons-content-toggle__label',
506 ]
507 );
508
509 $this->add_control(
510 'kng_label_color',
511 [
512 'label' => esc_html__('Label', 'king-addons'),
513 'type' => Controls_Manager::COLOR,
514 'selectors' => [
515 '{{WRAPPER}} .king-addons-content-toggle__label' => 'color: {{VALUE}};',
516 ],
517 ]
518 );
519
520 $this->add_control(
521 'kng_label_active_color',
522 [
523 'label' => esc_html__('Label Active', 'king-addons'),
524 'type' => Controls_Manager::COLOR,
525 'selectors' => [
526 '{{WRAPPER}} .king-addons-content-toggle__label.is-active' => 'color: {{VALUE}};',
527 ],
528 ]
529 );
530
531 $this->end_controls_section();
532 }
533
534 /**
535 * Register content style controls.
536 *
537 * @return void
538 */
539 public function register_style_content_controls(): void
540 {
541 $this->start_controls_section(
542 'kng_content_style_section',
543 [
544 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Content Area', 'king-addons'),
545 'tab' => Controls_Manager::TAB_STYLE,
546 ]
547 );
548
549 $this->add_group_control(
550 Group_Control_Background::get_type(),
551 [
552 'name' => 'kng_pane_background',
553 'types' => ['classic', 'gradient'],
554 'selector' => '{{WRAPPER}} .king-addons-content-toggle__pane',
555 ]
556 );
557
558 $this->add_group_control(
559 Group_Control_Border::get_type(),
560 [
561 'name' => 'kng_pane_border',
562 'selector' => '{{WRAPPER}} .king-addons-content-toggle__pane',
563 ]
564 );
565
566 $this->add_responsive_control(
567 'kng_pane_radius',
568 [
569 'label' => esc_html__('Border Radius', 'king-addons'),
570 'type' => Controls_Manager::SLIDER,
571 'size_units' => ['px'],
572 'range' => [
573 'px' => [
574 'min' => 0,
575 'max' => 50,
576 ],
577 ],
578 'selectors' => [
579 '{{WRAPPER}} .king-addons-content-toggle__pane' => 'border-radius: {{SIZE}}{{UNIT}};',
580 ],
581 ]
582 );
583
584 $this->add_responsive_control(
585 'kng_pane_padding',
586 [
587 'label' => esc_html__('Padding', 'king-addons'),
588 'type' => Controls_Manager::DIMENSIONS,
589 'size_units' => ['px', 'em', '%'],
590 'selectors' => [
591 '{{WRAPPER}} .king-addons-content-toggle__pane' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
592 ],
593 ]
594 );
595
596 $this->add_responsive_control(
597 'kng_pane_gap',
598 [
599 'label' => esc_html__('Content Gap', 'king-addons'),
600 'type' => Controls_Manager::SLIDER,
601 'size_units' => ['px'],
602 'range' => [
603 'px' => [
604 'min' => 0,
605 'max' => 48,
606 ],
607 ],
608 'selectors' => [
609 '{{WRAPPER}} .king-addons-content-toggle__panes' => 'gap: {{SIZE}}{{UNIT}};',
610 ],
611 ]
612 );
613
614 $this->add_group_control(
615 Group_Control_Box_Shadow::get_type(),
616 [
617 'name' => 'kng_pane_shadow',
618 'selector' => '{{WRAPPER}} .king-addons-content-toggle__pane',
619 ]
620 );
621
622 $this->add_group_control(
623 Group_Control_Typography::get_type(),
624 [
625 'name' => 'kng_content_typography',
626 'selector' => '{{WRAPPER}} .king-addons-content-toggle__pane',
627 ]
628 );
629
630 $this->add_control(
631 'kng_content_color',
632 [
633 'label' => esc_html__('Text', 'king-addons'),
634 'type' => Controls_Manager::COLOR,
635 'selectors' => [
636 '{{WRAPPER}} .king-addons-content-toggle__pane' => 'color: {{VALUE}};',
637 ],
638 ]
639 );
640
641 $this->end_controls_section();
642 }
643
644 /**
645 * Render the Pro feature promo section.
646 *
647 * @return void
648 */
649 public function register_pro_features_notice(): void
650 {
651 Core::renderProFeaturesSection(
652 $this,
653 '',
654 Controls_Manager::RAW_HTML,
655 'content-toggle',
656 [
657 'Use Elementor templates for primary and secondary areas',
658 'Add icons to primary and secondary labels',
659 'Control external CSS selectors to show or hide per state',
660 'Choose between fade and slide animations',
661 'Custom active/hidden classes for synced selectors',
662 ]
663 );
664 }
665
666 /**
667 * Render widget output on the frontend.
668 *
669 * @return void
670 */
671 public function render(): void
672 {
673 $settings = $this->get_settings_for_display();
674 $this->render_output($settings);
675 }
676
677 /**
678 * Render widget output using provided settings.
679 *
680 * @param array<string, mixed> $settings Widget settings.
681 *
682 * @return void
683 */
684 public function render_output(array $settings): void
685 {
686 $active_state = $this->get_default_state($settings);
687 $primary_targets = isset($settings['kng_primary_target_selectors']) ? trim((string) $settings['kng_primary_target_selectors']) : '';
688 $secondary_targets = isset($settings['kng_secondary_target_selectors']) ? trim((string) $settings['kng_secondary_target_selectors']) : '';
689 $primary_hide = isset($settings['kng_primary_hide_selectors']) ? trim((string) $settings['kng_primary_hide_selectors']) : '';
690 $secondary_hide = isset($settings['kng_secondary_hide_selectors']) ? trim((string) $settings['kng_secondary_hide_selectors']) : '';
691 $active_class = isset($settings['kng_active_class_name']) && '' !== $settings['kng_active_class_name']
692 ? sanitize_text_field((string) $settings['kng_active_class_name'])
693 : 'is-visible';
694 $hidden_class = isset($settings['kng_hidden_class_name']) && '' !== $settings['kng_hidden_class_name']
695 ? sanitize_text_field((string) $settings['kng_hidden_class_name'])
696 : 'is-hidden';
697
698 $wrapper_classes = [
699 'king-addons-content-toggle',
700 $active_state === 'secondary'
701 ? 'king-addons-content-toggle--secondary-active'
702 : 'king-addons-content-toggle--primary-active',
703 ];
704
705 $primary_pane_id = 'king-addons-content-toggle-primary-' . $this->get_id();
706 $secondary_pane_id = 'king-addons-content-toggle-secondary-' . $this->get_id();
707
708 $this->add_render_attribute('wrapper', 'class', $wrapper_classes);
709 $this->add_render_attribute('wrapper', 'data-default-state', $active_state);
710 $this->add_render_attribute('wrapper', 'data-animation', $settings['kng_animation_style'] ?? 'fade');
711 $this->add_render_attribute('wrapper', 'data-primary-targets', $primary_targets);
712 $this->add_render_attribute('wrapper', 'data-secondary-targets', $secondary_targets);
713 $this->add_render_attribute('wrapper', 'data-primary-hide', $primary_hide);
714 $this->add_render_attribute('wrapper', 'data-secondary-hide', $secondary_hide);
715 $this->add_render_attribute('wrapper', 'data-active-class', $active_class);
716 $this->add_render_attribute('wrapper', 'data-hidden-class', $hidden_class);
717
718 ?>
719 <div <?php echo $this->get_render_attribute_string('wrapper'); ?>>
720 <?php $this->render_toggle_header($settings, $active_state, $primary_pane_id, $secondary_pane_id); ?>
721 <?php $this->render_panes($settings, $active_state, $primary_pane_id, $secondary_pane_id); ?>
722 </div>
723 <?php
724 }
725
726 /**
727 * Render the toggle header.
728 *
729 * @param array<string, mixed> $settings Widget settings.
730 * @param string $active_state Active pane identifier.
731 * @param string $primary_pane_id Primary pane HTML id.
732 * @param string $secondary_pane_id Secondary pane HTML id.
733 *
734 * @return void
735 */
736 public function render_toggle_header(array $settings, string $active_state, string $primary_pane_id, string $secondary_pane_id): void
737 {
738 $primary_label = $settings['kng_toggle_label_primary'] ?? esc_html__('Primary', 'king-addons');
739 $secondary_label = $settings['kng_toggle_label_secondary'] ?? esc_html__('Secondary', 'king-addons');
740
741 ?>
742 <div class="king-addons-content-toggle__header" role="group" aria-label="<?php echo esc_attr__('Content toggle', 'king-addons'); ?>">
743 <button
744 type="button"
745 class="king-addons-content-toggle__label king-addons-content-toggle__label--primary <?php echo $active_state === 'primary' ? 'is-active' : ''; ?>"
746 data-target="primary"
747 aria-pressed="<?php echo $active_state === 'primary' ? 'true' : 'false'; ?>"
748 aria-controls="<?php echo esc_attr($primary_pane_id); ?>"
749 >
750 <?php echo $this->render_label_icon($settings, 'primary'); ?>
751 <span class="king-addons-content-toggle__label-text"><?php echo esc_html($primary_label); ?></span>
752 </button>
753
754 <button
755 type="button"
756 class="king-addons-content-toggle__switch"
757 role="switch"
758 aria-checked="<?php echo $active_state === 'secondary' ? 'true' : 'false'; ?>"
759 aria-label="<?php echo esc_attr__('Toggle content', 'king-addons'); ?>"
760 data-target="<?php echo $active_state === 'primary' ? 'secondary' : 'primary'; ?>"
761 >
762 <span class="king-addons-content-toggle__thumb" aria-hidden="true"></span>
763 </button>
764
765 <button
766 type="button"
767 class="king-addons-content-toggle__label king-addons-content-toggle__label--secondary <?php echo $active_state === 'secondary' ? 'is-active' : ''; ?>"
768 data-target="secondary"
769 aria-pressed="<?php echo $active_state === 'secondary' ? 'true' : 'false'; ?>"
770 aria-controls="<?php echo esc_attr($secondary_pane_id); ?>"
771 >
772 <?php echo $this->render_label_icon($settings, 'secondary'); ?>
773 <span class="king-addons-content-toggle__label-text"><?php echo esc_html($secondary_label); ?></span>
774 </button>
775 </div>
776 <?php
777 }
778
779 /**
780 * Render the content panes.
781 *
782 * @param array<string, mixed> $settings Widget settings.
783 * @param string $active_state Active pane identifier.
784 * @param string $primary_pane_id Primary pane HTML id.
785 * @param string $secondary_pane_id Secondary pane HTML id.
786 *
787 * @return void
788 */
789 public function render_panes(array $settings, string $active_state, string $primary_pane_id, string $secondary_pane_id): void
790 {
791 ?>
792 <div class="king-addons-content-toggle__panes">
793 <?php $this->render_single_pane($settings, 'primary', $primary_pane_id, $active_state === 'primary'); ?>
794 <?php $this->render_single_pane($settings, 'secondary', $secondary_pane_id, $active_state === 'secondary'); ?>
795 </div>
796 <?php
797 }
798
799 /**
800 * Render a single content pane.
801 *
802 * @param array<string, mixed> $settings Widget settings.
803 * @param string $context Pane context.
804 * @param string $pane_id Pane HTML id.
805 * @param bool $is_active Whether pane is active.
806 *
807 * @return void
808 */
809 public function render_single_pane(array $settings, string $context, string $pane_id, bool $is_active): void
810 {
811 $content_html = $this->get_content_html($settings, $context);
812
813 if ('' === $content_html) {
814 return;
815 }
816
817 ?>
818 <div
819 id="<?php echo esc_attr($pane_id); ?>"
820 class="king-addons-content-toggle__pane king-addons-content-toggle__pane--<?php echo esc_attr($context); ?> <?php echo $is_active ? 'is-active' : ''; ?>"
821 role="region"
822 aria-live="polite"
823 <?php echo $is_active ? '' : 'hidden'; ?>
824 >
825 <?php echo $content_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
826 </div>
827 <?php
828 }
829
830 /**
831 * Get default state from settings.
832 *
833 * @param array<string, mixed> $settings Widget settings.
834 *
835 * @return string
836 */
837 public function get_default_state(array $settings): string
838 {
839 $state = $settings['kng_default_state'] ?? 'primary';
840 return 'secondary' === $state ? 'secondary' : 'primary';
841 }
842
843 /**
844 * Get content type for a context.
845 *
846 * @param array<string, mixed> $settings Widget settings.
847 * @param string $context Context identifier.
848 *
849 * @return string
850 */
851 public function get_content_type(array $settings, string $context): string
852 {
853 $key = 'kng_' . $context . '_source';
854 $value = $settings[$key] ?? 'text';
855
856 if (!in_array($value, ['text', 'image'], true)) {
857 return 'text';
858 }
859
860 return $value;
861 }
862
863 /**
864 * Get content HTML for a context.
865 *
866 * @param array<string, mixed> $settings Widget settings.
867 * @param string $context Context identifier.
868 *
869 * @return string
870 */
871 public function get_content_html(array $settings, string $context): string
872 {
873 return $this->get_content_html_base($settings, $context);
874 }
875
876 /**
877 * Get base content HTML for a context.
878 *
879 * This method exists to allow the Pro version to extend content rendering
880 * without calling `parent::` methods.
881 *
882 * @param array<string, mixed> $settings Widget settings.
883 * @param string $context Context identifier.
884 *
885 * @return string
886 */
887 public function get_content_html_base(array $settings, string $context): string
888 {
889 $type = $this->get_content_type($settings, $context);
890
891 if ('image' === $type) {
892 return $this->get_image_html($settings, $context);
893 }
894
895 $key = 'kng_' . $context . '_content';
896 $content = $settings[$key] ?? '';
897
898 return wp_kses_post($content);
899 }
900
901 /**
902 * Get image HTML for a context.
903 *
904 * @param array<string, mixed> $settings Widget settings.
905 * @param string $context Context identifier.
906 *
907 * @return string
908 */
909 public function get_image_html(array $settings, string $context): string
910 {
911 $image_key = 'kng_' . $context . '_image';
912 $image = $settings[$image_key] ?? null;
913
914 if (empty($image['id']) && empty($image['url'])) {
915 return '';
916 }
917
918 $image_html = Group_Control_Image_Size::get_attachment_image_html(
919 $settings,
920 $image_key,
921 $image_key
922 );
923
924 if (empty($image_html) && !empty($image['url'])) {
925 $alt = !empty($image['alt']) ? $image['alt'] : $this->get_title();
926 $image_html = '<img src="' . esc_url($image['url']) . '" alt="' . esc_attr($alt) . '" />';
927 }
928
929 return $image_html;
930 }
931
932 /**
933 * Render label icon if provided.
934 *
935 * @param array<string, mixed> $settings Widget settings.
936 * @param string $context Context identifier.
937 *
938 * @return string
939 */
940 public function render_label_icon(array $settings, string $context): string
941 {
942 $icon_key = 'kng_' . $context . '_icon';
943 $icon = $settings[$icon_key] ?? null;
944
945 if (empty($icon)) {
946 return '';
947 }
948
949 ob_start();
950 Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']);
951
952 return '<span class="king-addons-content-toggle__label-icon">' . ob_get_clean() . '</span>';
953 }
954
955 /**
956 * Get Elementor template content.
957 *
958 * @param int $template_id Template id.
959 * @param bool $include_css Whether to include template CSS.
960 *
961 * @return string
962 */
963 public function get_template_content(int $template_id, bool $include_css = true): string
964 {
965 if (empty($template_id)) {
966 return '';
967 }
968
969 $has_css = $include_css && 'internal' === get_option('elementor_css_print_method');
970
971 return Plugin::instance()->frontend->get_builder_content_for_display($template_id, $has_css);
972 }
973
974 /**
975 * Get Elementor templates options.
976 *
977 * @return array<string, string>
978 */
979 public function get_elementor_templates_options(): array
980 {
981 $options = [];
982 $templates = Plugin::$instance->templates_manager->get_source('local')->get_items();
983
984 if (!empty($templates)) {
985 foreach ($templates as $template) {
986 $options[$template['template_id']] = $template['title'];
987 }
988 }
989
990 return $options;
991 }
992 }
993
994
995
996
997