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 / 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.49, at includes/widgets/Advanced_Callout_Box/Advanced_Callout_Box.php

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