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 / Advanced_Callout_Box / Advanced_Callout_Box.php

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

1,073 lines 33.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Advanced Callout Box Widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Box_Shadow;
12 use Elementor\Group_Control_Border;
13 use Elementor\Group_Control_Typography;
14 use Elementor\Icons_Manager;
15 use Elementor\Widget_Base;
16
17 if (!defined('ABSPATH')) {
18 exit;
19 }
20
21 /**
22 * Callout box widget for notes, tips, and warnings.
23 */
24 class Advanced_Callout_Box extends Widget_Base
25 {
26 /**
27 * Widget slug.
28 *
29 * @return string
30 */
31 public function get_name(): string
32 {
33 return 'king-addons-advanced-callout-box';
34 }
35
36 /**
37 * Widget title.
38 *
39 * @return string
40 */
41 public function get_title(): string
42 {
43 return esc_html__('Advanced Callout Box', 'king-addons');
44 }
45
46 /**
47 * Widget icon.
48 *
49 * @return string
50 */
51 public function get_icon(): string
52 {
53 return 'king-addons-icon king-addons-advanced-callout-box';
54 }
55
56 /**
57 * Style dependencies.
58 *
59 * @return array<int, string>
60 */
61 public function get_style_depends(): array
62 {
63 return [
64 KING_ADDONS_ASSETS_UNIQUE_KEY . '-advanced-callout-box-style',
65 'elementor-icons-fa-solid',
66 'elementor-icons-fa-regular',
67 'elementor-icons-fa-brands',
68 ];
69 }
70
71 /**
72 * Script dependencies.
73 *
74 * @return array<int, string>
75 */
76 public function get_script_depends(): array
77 {
78 return [];
79 }
80
81 /**
82 * Categories.
83 *
84 * @return array<int, string>
85 */
86 public function get_categories(): array
87 {
88 return ['king-addons'];
89 }
90
91 /**
92 * Keywords.
93 *
94 * @return array<int, string>
95 */
96 public function get_keywords(): array
97 {
98 return ['callout', 'notice', 'alert', 'note', 'tip'];
99 }
100
101 public function get_custom_help_url()
102 {
103 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
104 }
105
106 /**
107 * Register controls.
108 *
109 * @return void
110 */
111 public function register_controls(): void
112 {
113 $this->register_content_controls();
114 $this->register_cta_controls();
115 $this->register_style_controls();
116 $this->register_pro_notice_controls();
117 }
118
119 /**
120 * Render widget output.
121 *
122 * @return void
123 */
124 public function render(): void
125 {
126 $settings = $this->get_settings_for_display();
127 $type = $this->sanitize_type($settings['kng_type'] ?? 'note');
128 $title = $settings['kng_title'] ?? '';
129 $content = $settings['kng_content'] ?? '';
130 $show_icon = ($settings['kng_show_icon'] ?? 'yes') === 'yes';
131 $icon_position = $this->sanitize_icon_position($settings['kng_icon_position'] ?? 'left');
132 $accent_enabled = ($settings['kng_accent_enable'] ?? 'yes') === 'yes';
133 $align = $this->sanitize_align($settings['kng_content_alignment'] ?? 'left');
134
135 if (!$show_icon) {
136 $icon_position = 'none';
137 }
138
139 $title_id = 'king-addons-callout-title-' . $this->get_id();
140 $content_id = 'king-addons-callout-content-' . $this->get_id();
141
142 $wrapper_attrs = $this->get_wrapper_attributes([
143 'type' => $type,
144 'icon_position' => $icon_position,
145 'accent' => $accent_enabled ? 'yes' : 'no',
146 'align' => $align,
147 'title_id' => !empty($title) ? $title_id : '',
148 'content_id' => !empty($content) ? $content_id : '',
149 ]);
150
151 $icon = null;
152 if ('none' !== $icon_position) {
153 $override_icon = ($settings['kng_icon_override'] ?? '') === 'yes';
154 if ($override_icon && !empty($settings['kng_custom_icon']['value'])) {
155 $icon = $settings['kng_custom_icon'];
156 } else {
157 $icon = $this->get_default_icon($type);
158 }
159 }
160
161 $button_enabled = ($settings['kng_button_enable'] ?? '') === 'yes';
162 $button_text = $settings['kng_button_text'] ?? '';
163 $button_link = $settings['kng_button_link'] ?? [];
164
165 $href = is_array($button_link) ? ($button_link['url'] ?? '') : '';
166 $is_external = is_array($button_link) && !empty($button_link['is_external']);
167 $nofollow = is_array($button_link) && !empty($button_link['nofollow']);
168 $rels = [];
169 if ($is_external) {
170 $rels[] = 'noopener';
171 $rels[] = 'noreferrer';
172 }
173 if ($nofollow) {
174 $rels[] = 'nofollow';
175 }
176 $rel_attr = !empty($rels) ? ' rel="' . esc_attr(implode(' ', array_unique($rels))) . '"' : '';
177 $target_attr = $is_external ? ' target="_blank"' : '';
178
179 $title_tag = $this->sanitize_title_tag($settings['kng_title_tag'] ?? 'h4');
180 ?>
181 <div class="king-addons-advanced-callout" <?php echo $wrapper_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
182 <div class="king-addons-advanced-callout__inner">
183 <?php if ($icon && 'none' !== $icon_position) : ?>
184 <span class="king-addons-advanced-callout__icon" aria-hidden="true">
185 <?php Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']); ?>
186 </span>
187 <?php endif; ?>
188
189 <div class="king-addons-advanced-callout__body">
190 <?php if (!empty($title)) : ?>
191 <<?php echo esc_attr($title_tag); ?> id="<?php echo esc_attr($title_id); ?>" class="king-addons-advanced-callout__title">
192 <?php echo esc_html($title); ?>
193 </<?php echo esc_attr($title_tag); ?>>
194 <?php endif; ?>
195
196 <?php if (!empty($content)) : ?>
197 <div id="<?php echo esc_attr($content_id); ?>" class="king-addons-advanced-callout__content">
198 <?php echo wp_kses_post($content); ?>
199 </div>
200 <?php endif; ?>
201
202 <?php if ($button_enabled && !empty($button_text)) : ?>
203 <?php if (!empty($href)) : ?>
204 <a class="king-addons-advanced-callout__button" href="<?php echo esc_url($href); ?>"<?php echo $target_attr . $rel_attr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
205 <?php echo esc_html($button_text); ?>
206 </a>
207 <?php else : ?>
208 <span class="king-addons-advanced-callout__button" aria-disabled="true">
209 <?php echo esc_html($button_text); ?>
210 </span>
211 <?php endif; ?>
212 <?php endif; ?>
213 </div>
214 </div>
215 </div>
216 <?php
217 }
218
219 /**
220 * Content controls.
221 *
222 * @return void
223 */
224 protected function register_content_controls(): void
225 {
226 $this->start_controls_section(
227 'kng_content_section',
228 [
229 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Content', 'king-addons'),
230 'tab' => Controls_Manager::TAB_CONTENT,
231 ]
232 );
233
234 $this->add_control(
235 'kng_type',
236 [
237 'label' => esc_html__('Type', 'king-addons'),
238 'type' => Controls_Manager::SELECT,
239 'default' => 'note',
240 'options' => [
241 'note' => esc_html__('Note', 'king-addons'),
242 'tip' => esc_html__('Tip', 'king-addons'),
243 'warning' => esc_html__('Warning', 'king-addons'),
244 ],
245 ]
246 );
247
248 $this->add_control(
249 'kng_title',
250 [
251 'label' => esc_html__('Title', 'king-addons'),
252 'type' => Controls_Manager::TEXT,
253 'dynamic' => [
254 'active' => true,
255 ],
256 'default' => esc_html__('Note', 'king-addons'),
257 'label_block' => true,
258 ]
259 );
260
261 $this->add_control(
262 'kng_title_tag',
263 [
264 'label' => esc_html__('Title HTML Tag', 'king-addons'),
265 'type' => Controls_Manager::SELECT,
266 'default' => 'h4',
267 'options' => [
268 'h1' => 'H1',
269 'h2' => 'H2',
270 'h3' => 'H3',
271 'h4' => 'H4',
272 'h5' => 'H5',
273 'h6' => 'H6',
274 'div' => 'DIV',
275 'p' => 'P',
276 ],
277 ]
278 );
279
280 $this->add_control(
281 'kng_content',
282 [
283 'label' => esc_html__('Content', 'king-addons'),
284 'type' => Controls_Manager::WYSIWYG,
285 'dynamic' => [
286 'active' => true,
287 ],
288 'default' => esc_html__('Add your callout content here.', 'king-addons'),
289 ]
290 );
291
292 $this->add_control(
293 'kng_show_icon',
294 [
295 'label' => esc_html__('Show Icon', 'king-addons'),
296 'type' => Controls_Manager::SWITCHER,
297 'return_value' => 'yes',
298 'default' => 'yes',
299 'separator' => 'before',
300 ]
301 );
302
303 $this->add_control(
304 'kng_icon_position',
305 [
306 'label' => esc_html__('Icon Position', 'king-addons'),
307 'type' => Controls_Manager::CHOOSE,
308 'toggle' => true,
309 'default' => 'left',
310 'options' => [
311 'left' => [
312 'title' => esc_html__('Left', 'king-addons'),
313 'icon' => 'eicon-h-align-left',
314 ],
315 'top' => [
316 'title' => esc_html__('Top', 'king-addons'),
317 'icon' => 'eicon-v-align-top',
318 ],
319 'none' => [
320 'title' => esc_html__('None', 'king-addons'),
321 'icon' => 'eicon-close',
322 ],
323 ],
324 'condition' => [
325 'kng_show_icon' => 'yes',
326 ],
327 ]
328 );
329
330 $this->add_control(
331 'kng_icon_override',
332 [
333 'label' => esc_html__('Custom Icon', 'king-addons'),
334 'type' => Controls_Manager::SWITCHER,
335 'return_value' => 'yes',
336 'default' => '',
337 'condition' => [
338 'kng_show_icon' => 'yes',
339 'kng_icon_position!' => 'none',
340 ],
341 ]
342 );
343
344 $this->add_control(
345 'kng_custom_icon',
346 [
347 'label' => esc_html__('Select Icon', 'king-addons'),
348 'type' => Controls_Manager::ICONS,
349 'default' => [
350 'value' => 'fas fa-info-circle',
351 'library' => 'fa-solid',
352 ],
353 'condition' => [
354 'kng_show_icon' => 'yes',
355 'kng_icon_position!' => 'none',
356 'kng_icon_override' => 'yes',
357 ],
358 ]
359 );
360
361 $this->end_controls_section();
362 }
363
364 /**
365 * CTA controls.
366 *
367 * @return void
368 */
369 protected function register_cta_controls(): void
370 {
371 $this->start_controls_section(
372 'kng_cta_section',
373 [
374 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('CTA', 'king-addons'),
375 'tab' => Controls_Manager::TAB_CONTENT,
376 ]
377 );
378
379 $this->add_control(
380 'kng_button_enable',
381 [
382 'label' => esc_html__('Button', 'king-addons'),
383 'type' => Controls_Manager::SWITCHER,
384 'return_value' => 'yes',
385 'default' => '',
386 ]
387 );
388
389 $this->add_control(
390 'kng_button_text',
391 [
392 'label' => esc_html__('Button Text', 'king-addons'),
393 'type' => Controls_Manager::TEXT,
394 'dynamic' => [
395 'active' => true,
396 ],
397 'default' => esc_html__('Learn more', 'king-addons'),
398 'condition' => [
399 'kng_button_enable' => 'yes',
400 ],
401 ]
402 );
403
404 $this->add_control(
405 'kng_button_link',
406 [
407 'label' => esc_html__('Button Link', 'king-addons'),
408 'type' => Controls_Manager::URL,
409 'dynamic' => [
410 'active' => true,
411 ],
412 'placeholder' => esc_html__('https://', 'king-addons'),
413 'condition' => [
414 'kng_button_enable' => 'yes',
415 ],
416 ]
417 );
418
419 $this->end_controls_section();
420 }
421
422 /**
423 * Style controls.
424 *
425 * @return void
426 */
427 protected function register_style_controls(): void
428 {
429 $this->start_controls_section(
430 'kng_style_box_section',
431 [
432 'label' => esc_html__('Box', 'king-addons'),
433 'tab' => Controls_Manager::TAB_STYLE,
434 ]
435 );
436
437 $this->add_control(
438 'kng_background_color',
439 [
440 'label' => esc_html__('Background Color', 'king-addons'),
441 'type' => Controls_Manager::COLOR,
442 'selectors' => [
443 '{{WRAPPER}} .king-addons-advanced-callout' => 'background-color: {{VALUE}};',
444 ],
445 ]
446 );
447
448 $this->add_group_control(
449 Group_Control_Border::get_type(),
450 [
451 'name' => 'kng_border',
452 'selector' => '{{WRAPPER}} .king-addons-advanced-callout',
453 ]
454 );
455
456 $this->add_group_control(
457 Group_Control_Box_Shadow::get_type(),
458 [
459 'name' => 'kng_box_shadow',
460 'selector' => '{{WRAPPER}} .king-addons-advanced-callout',
461 ]
462 );
463
464 $this->add_responsive_control(
465 'kng_border_radius',
466 [
467 'label' => esc_html__('Border Radius', 'king-addons'),
468 'type' => Controls_Manager::SLIDER,
469 'size_units' => ['px', '%'],
470 'range' => [
471 'px' => [
472 'min' => 0,
473 'max' => 80,
474 ],
475 '%' => [
476 'min' => 0,
477 'max' => 50,
478 ],
479 ],
480 'selectors' => [
481 '{{WRAPPER}} .king-addons-advanced-callout' => 'border-radius: {{SIZE}}{{UNIT}};',
482 ],
483 ]
484 );
485
486 $this->add_responsive_control(
487 'kng_padding',
488 [
489 'label' => esc_html__('Padding', 'king-addons'),
490 'type' => Controls_Manager::DIMENSIONS,
491 'size_units' => ['px', 'em', '%'],
492 'selectors' => [
493 '{{WRAPPER}} .king-addons-advanced-callout__inner' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
494 ],
495 ]
496 );
497
498 $this->add_responsive_control(
499 'kng_content_alignment',
500 [
501 'label' => esc_html__('Content Alignment', 'king-addons'),
502 'type' => Controls_Manager::CHOOSE,
503 'toggle' => true,
504 'default' => 'left',
505 'options' => [
506 'left' => [
507 'title' => esc_html__('Left', 'king-addons'),
508 'icon' => 'eicon-text-align-left',
509 ],
510 'center' => [
511 'title' => esc_html__('Center', 'king-addons'),
512 'icon' => 'eicon-text-align-center',
513 ],
514 'right' => [
515 'title' => esc_html__('Right', 'king-addons'),
516 'icon' => 'eicon-text-align-right',
517 ],
518 ],
519 'selectors' => [
520 '{{WRAPPER}} .king-addons-advanced-callout__body' => 'text-align: {{VALUE}};',
521 ],
522 ]
523 );
524
525 $this->add_responsive_control(
526 'kng_icon_gap',
527 [
528 'label' => esc_html__('Icon Gap', 'king-addons'),
529 'type' => Controls_Manager::SLIDER,
530 'size_units' => ['px', 'em'],
531 'range' => [
532 'px' => [
533 'min' => 0,
534 'max' => 60,
535 ],
536 'em' => [
537 'min' => 0,
538 'max' => 6,
539 ],
540 ],
541 'selectors' => [
542 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-gap: {{SIZE}}{{UNIT}};',
543 ],
544 ]
545 );
546
547 $this->add_responsive_control(
548 'kng_margin_bottom',
549 [
550 'label' => esc_html__('Margin Bottom', 'king-addons'),
551 'type' => Controls_Manager::SLIDER,
552 'size_units' => ['px', 'em', '%'],
553 'range' => [
554 'px' => [
555 'min' => 0,
556 'max' => 200,
557 ],
558 'em' => [
559 'min' => 0,
560 'max' => 12,
561 ],
562 '%' => [
563 'min' => 0,
564 'max' => 100,
565 ],
566 ],
567 'selectors' => [
568 '{{WRAPPER}} .king-addons-advanced-callout' => 'margin-bottom: {{SIZE}}{{UNIT}};',
569 ],
570 ]
571 );
572
573 $this->add_control(
574 'kng_accent_enable',
575 [
576 'label' => esc_html__('Left Accent Bar', 'king-addons'),
577 'type' => Controls_Manager::SWITCHER,
578 'return_value' => 'yes',
579 'default' => 'yes',
580 'separator' => 'before',
581 ]
582 );
583
584 $this->add_control(
585 'kng_accent_color',
586 [
587 'label' => esc_html__('Accent Color', 'king-addons'),
588 'type' => Controls_Manager::COLOR,
589 'selectors' => [
590 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-accent-color: {{VALUE}}; --ka-callout-button-bg: {{VALUE}};',
591 ],
592 ]
593 );
594
595 $this->add_responsive_control(
596 'kng_accent_width',
597 [
598 'label' => esc_html__('Accent Bar Width', 'king-addons'),
599 'type' => Controls_Manager::SLIDER,
600 'size_units' => ['px'],
601 'range' => [
602 'px' => [
603 'min' => 1,
604 'max' => 16,
605 ],
606 ],
607 'selectors' => [
608 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-accent-width: {{SIZE}}{{UNIT}};',
609 ],
610 'condition' => [
611 'kng_accent_enable' => 'yes',
612 ],
613 ]
614 );
615
616 $this->end_controls_section();
617
618 $this->start_controls_section(
619 'kng_style_icon_section',
620 [
621 'label' => esc_html__('Icon', 'king-addons'),
622 'tab' => Controls_Manager::TAB_STYLE,
623 'condition' => [
624 'kng_show_icon' => 'yes',
625 ],
626 ]
627 );
628
629 $this->add_control(
630 'kng_icon_color',
631 [
632 'label' => esc_html__('Color', 'king-addons'),
633 'type' => Controls_Manager::COLOR,
634 'selectors' => [
635 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-icon: {{VALUE}};',
636 ],
637 ]
638 );
639
640 $this->add_responsive_control(
641 'kng_icon_size',
642 [
643 'label' => esc_html__('Size', 'king-addons'),
644 'type' => Controls_Manager::SLIDER,
645 'size_units' => ['px', 'em'],
646 'range' => [
647 'px' => [
648 'min' => 12,
649 'max' => 80,
650 ],
651 'em' => [
652 'min' => 0.5,
653 'max' => 6,
654 ],
655 ],
656 'selectors' => [
657 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-icon-size: {{SIZE}}{{UNIT}};',
658 ],
659 ]
660 );
661
662 $this->end_controls_section();
663
664 $this->start_controls_section(
665 'kng_style_title_section',
666 [
667 'label' => esc_html__('Title', 'king-addons'),
668 'tab' => Controls_Manager::TAB_STYLE,
669 ]
670 );
671
672 $this->add_group_control(
673 Group_Control_Typography::get_type(),
674 [
675 'name' => 'kng_title_typography',
676 'selector' => '{{WRAPPER}} .king-addons-advanced-callout__title',
677 ]
678 );
679
680 $this->add_control(
681 'kng_title_color',
682 [
683 'label' => esc_html__('Color', 'king-addons'),
684 'type' => Controls_Manager::COLOR,
685 'selectors' => [
686 '{{WRAPPER}} .king-addons-advanced-callout__title' => 'color: {{VALUE}};',
687 ],
688 ]
689 );
690
691 $this->end_controls_section();
692
693 $this->start_controls_section(
694 'kng_style_content_section',
695 [
696 'label' => esc_html__('Content', 'king-addons'),
697 'tab' => Controls_Manager::TAB_STYLE,
698 ]
699 );
700
701 $this->add_group_control(
702 Group_Control_Typography::get_type(),
703 [
704 'name' => 'kng_content_typography',
705 'selector' => '{{WRAPPER}} .king-addons-advanced-callout__content',
706 ]
707 );
708
709 $this->add_control(
710 'kng_content_color',
711 [
712 'label' => esc_html__('Color', 'king-addons'),
713 'type' => Controls_Manager::COLOR,
714 'selectors' => [
715 '{{WRAPPER}} .king-addons-advanced-callout__content' => 'color: {{VALUE}};',
716 ],
717 ]
718 );
719
720 $this->end_controls_section();
721
722 $this->start_controls_section(
723 'kng_style_button_section',
724 [
725 'label' => esc_html__('Button', 'king-addons'),
726 'tab' => Controls_Manager::TAB_STYLE,
727 'condition' => [
728 'kng_button_enable' => 'yes',
729 ],
730 ]
731 );
732
733 $this->add_group_control(
734 Group_Control_Typography::get_type(),
735 [
736 'name' => 'kng_button_typography',
737 'selector' => '{{WRAPPER}} .king-addons-advanced-callout__button',
738 ]
739 );
740
741 $this->add_responsive_control(
742 'kng_button_padding',
743 [
744 'label' => esc_html__('Padding', 'king-addons'),
745 'type' => Controls_Manager::DIMENSIONS,
746 'size_units' => ['px', 'em', '%'],
747 'selectors' => [
748 '{{WRAPPER}} .king-addons-advanced-callout__button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
749 ],
750 ]
751 );
752
753 $this->add_responsive_control(
754 'kng_button_spacing',
755 [
756 'label' => esc_html__('Spacing', 'king-addons'),
757 'type' => Controls_Manager::SLIDER,
758 'size_units' => ['px', 'em'],
759 'range' => [
760 'px' => [
761 'min' => 0,
762 'max' => 60,
763 ],
764 'em' => [
765 'min' => 0,
766 'max' => 6,
767 ],
768 ],
769 'selectors' => [
770 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-gap: {{SIZE}}{{UNIT}};',
771 ],
772 ]
773 );
774
775 $this->add_responsive_control(
776 'kng_button_radius',
777 [
778 'label' => esc_html__('Border Radius', 'king-addons'),
779 'type' => Controls_Manager::SLIDER,
780 'size_units' => ['px', '%'],
781 'range' => [
782 'px' => [
783 'min' => 0,
784 'max' => 80,
785 ],
786 '%' => [
787 'min' => 0,
788 'max' => 50,
789 ],
790 ],
791 'selectors' => [
792 '{{WRAPPER}} .king-addons-advanced-callout__button' => 'border-radius: {{SIZE}}{{UNIT}};',
793 ],
794 ]
795 );
796
797 $this->add_responsive_control(
798 'kng_button_border_width',
799 [
800 'label' => esc_html__('Border Width', 'king-addons'),
801 'type' => Controls_Manager::SLIDER,
802 'size_units' => ['px'],
803 'range' => [
804 'px' => [
805 'min' => 0,
806 'max' => 8,
807 ],
808 ],
809 'selectors' => [
810 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-border-width: {{SIZE}}{{UNIT}};',
811 ],
812 ]
813 );
814
815 $this->add_control(
816 'kng_button_border_style',
817 [
818 'label' => esc_html__('Border Style', 'king-addons'),
819 'type' => Controls_Manager::SELECT,
820 'default' => 'solid',
821 'options' => [
822 'none' => esc_html__('None', 'king-addons'),
823 'solid' => esc_html__('Solid', 'king-addons'),
824 'dashed' => esc_html__('Dashed', 'king-addons'),
825 'dotted' => esc_html__('Dotted', 'king-addons'),
826 'double' => esc_html__('Double', 'king-addons'),
827 ],
828 'selectors' => [
829 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-border-style: {{VALUE}};',
830 ],
831 ]
832 );
833
834 $this->start_controls_tabs('kng_button_style_tabs');
835
836 $this->start_controls_tab(
837 'kng_button_style_tab_normal',
838 [
839 'label' => esc_html__('Normal', 'king-addons'),
840 ]
841 );
842
843 $this->add_control(
844 'kng_button_background',
845 [
846 'label' => esc_html__('Background Color', 'king-addons'),
847 'type' => Controls_Manager::COLOR,
848 'selectors' => [
849 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-bg: {{VALUE}};',
850 ],
851 ]
852 );
853
854 $this->add_control(
855 'kng_button_color',
856 [
857 'label' => esc_html__('Text Color', 'king-addons'),
858 'type' => Controls_Manager::COLOR,
859 'selectors' => [
860 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-color: {{VALUE}};',
861 ],
862 ]
863 );
864
865 $this->add_control(
866 'kng_button_border_color',
867 [
868 'label' => esc_html__('Border Color', 'king-addons'),
869 'type' => Controls_Manager::COLOR,
870 'selectors' => [
871 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-border: {{VALUE}};',
872 ],
873 ]
874 );
875
876 $this->end_controls_tab();
877
878 $this->start_controls_tab(
879 'kng_button_style_tab_hover',
880 [
881 'label' => esc_html__('Hover', 'king-addons'),
882 ]
883 );
884
885 $this->add_control(
886 'kng_button_background_hover',
887 [
888 'label' => esc_html__('Background Color', 'king-addons'),
889 'type' => Controls_Manager::COLOR,
890 'selectors' => [
891 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-bg-hover: {{VALUE}}; --ka-callout-button-hover-filter: none;',
892 ],
893 ]
894 );
895
896 $this->add_control(
897 'kng_button_color_hover',
898 [
899 'label' => esc_html__('Text Color', 'king-addons'),
900 'type' => Controls_Manager::COLOR,
901 'selectors' => [
902 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-color-hover: {{VALUE}}; --ka-callout-button-hover-filter: none;',
903 ],
904 ]
905 );
906
907 $this->add_control(
908 'kng_button_border_color_hover',
909 [
910 'label' => esc_html__('Border Color', 'king-addons'),
911 'type' => Controls_Manager::COLOR,
912 'selectors' => [
913 '{{WRAPPER}} .king-addons-advanced-callout' => '--ka-callout-button-border-hover: {{VALUE}}; --ka-callout-button-hover-filter: none;',
914 ],
915 ]
916 );
917
918 $this->end_controls_tab();
919
920 $this->end_controls_tabs();
921
922 $this->end_controls_section();
923 }
924
925 /**
926 * Register Pro notice controls.
927 *
928 * @return void
929 */
930 public function register_pro_notice_controls(): void
931 {
932 if (!king_addons_can_use_pro()) {
933 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'advanced-callout-box', [
934 'Promo, Info, Success, and Custom types',
935 'Collapsible mode with accessible toggle',
936 'Copy-to-clipboard button with feedback',
937 'Dynamic content via ACF with fallbacks',
938 'Display conditions and preset library',
939 ]);
940 }
941 }
942
943 /**
944 * Sanitize callout type.
945 *
946 * @param string $type Type.
947 *
948 * @return string
949 */
950 protected function sanitize_type(string $type): string
951 {
952 $allowed = ['note', 'tip', 'warning', 'promo', 'info', 'success', 'custom'];
953 return in_array($type, $allowed, true) ? $type : 'note';
954 }
955
956 /**
957 * Sanitize icon position.
958 *
959 * @param string $position Position.
960 *
961 * @return string
962 */
963 protected function sanitize_icon_position(string $position): string
964 {
965 $allowed = ['left', 'top', 'none'];
966 return in_array($position, $allowed, true) ? $position : 'left';
967 }
968
969 /**
970 * Sanitize content alignment.
971 *
972 * @param string $align Alignment.
973 *
974 * @return string
975 */
976 protected function sanitize_align(string $align): string
977 {
978 $allowed = ['left', 'center', 'right'];
979 return in_array($align, $allowed, true) ? $align : 'left';
980 }
981
982 /**
983 * Sanitize title tag.
984 *
985 * @param string $tag Tag.
986 *
987 * @return string
988 */
989 protected function sanitize_title_tag(string $tag): string
990 {
991 $allowed = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'p', 'span'];
992 return in_array($tag, $allowed, true) ? $tag : 'h4';
993 }
994
995 /**
996 * Default icon map per type.
997 *
998 * @param string $type Type.
999 *
1000 * @return array<string, string>
1001 */
1002 protected function get_default_icon(string $type): array
1003 {
1004 $map = [
1005 'note' => [
1006 'value' => 'far fa-sticky-note',
1007 'library' => 'fa-regular',
1008 ],
1009 'tip' => [
1010 'value' => 'far fa-lightbulb',
1011 'library' => 'fa-regular',
1012 ],
1013 'warning' => [
1014 'value' => 'fas fa-exclamation-triangle',
1015 'library' => 'fa-solid',
1016 ],
1017 'promo' => [
1018 'value' => 'fas fa-bullhorn',
1019 'library' => 'fa-solid',
1020 ],
1021 'info' => [
1022 'value' => 'fas fa-info-circle',
1023 'library' => 'fa-solid',
1024 ],
1025 'success' => [
1026 'value' => 'fas fa-check-circle',
1027 'library' => 'fa-solid',
1028 ],
1029 'custom' => [
1030 'value' => 'fas fa-star',
1031 'library' => 'fa-solid',
1032 ],
1033 ];
1034
1035 return $map[$type] ?? $map['note'];
1036 }
1037
1038 /**
1039 * Build wrapper attributes.
1040 *
1041 * @param array<string, string> $settings Settings.
1042 *
1043 * @return string
1044 */
1045 protected function get_wrapper_attributes(array $settings): string
1046 {
1047 $attrs = [
1048 'data-type' => $settings['type'] ?? 'note',
1049 'data-icon-position' => $settings['icon_position'] ?? 'left',
1050 'data-accent' => $settings['accent'] ?? 'yes',
1051 'data-align' => $settings['align'] ?? 'left',
1052 'data-collapsible' => 'no',
1053 'data-copy' => 'no',
1054 'role' => 'note',
1055 ];
1056
1057 if (!empty($settings['title_id'])) {
1058 $attrs['aria-labelledby'] = $settings['title_id'];
1059 }
1060
1061 if (!empty($settings['content_id'])) {
1062 $attrs['aria-describedby'] = $settings['content_id'];
1063 }
1064
1065 $compiled = [];
1066 foreach ($attrs as $key => $value) {
1067 $compiled[] = esc_attr($key) . '="' . esc_attr($value) . '"';
1068 }
1069
1070 return implode(' ', $compiled);
1071 }
1072 }
1073