PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.49
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.49
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.49, at includes/widgets/Content_Toggle/Content_Toggle.php

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