PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.78
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.78
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 / Values_Circle_Infographic / Values_Circle_Infographic.php

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

839 lines 36.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace King_Addons;
4
5 use Elementor\Controls_Manager;
6 use Elementor\Group_Control_Typography;
7 use Elementor\Widget_Base;
8
9 if (!defined('ABSPATH')) {
10 exit;
11 }
12
13 class Values_Circle_Infographic extends Widget_Base
14 {
15 public function get_name(): string
16 {
17 return 'king-addons-values-circle-infographic';
18 }
19
20 public function get_title(): string
21 {
22 return esc_html__('Values Circle Infographic', 'king-addons');
23 }
24
25 public function get_icon(): string
26 {
27 return 'eicon-shape-circle';
28 }
29
30 public function get_style_depends(): array
31 {
32 return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-values-circle-infographic-style'];
33 }
34
35 public function get_script_depends(): array
36 {
37 return [
38 KING_ADDONS_ASSETS_UNIQUE_KEY . '-values-circle-infographic-script',
39 KING_ADDONS_ASSETS_UNIQUE_KEY . '-lottie-lottie',
40 ];
41 }
42
43 public function get_categories(): array
44 {
45 return ['king-addons'];
46 }
47
48 public function get_keywords(): array
49 {
50 return ['values', 'circle', 'infographic', 'diagram', 'king-addons'];
51 }
52
53 public function get_custom_help_url()
54 {
55 return 'mailto:bug@kingaddons.com?subject=Bug Report - King Addons&body=Please describe the issue';
56 }
57
58 protected function register_controls(): void
59 {
60 // ── Content: Center Image ───────────────────────────────────────
61 $this->start_controls_section(
62 'ka_values_circle_center_image_section',
63 [
64 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Center Image', 'king-addons'),
65 'tab' => Controls_Manager::TAB_CONTENT,
66 ]
67 );
68
69 $this->add_control(
70 'ka_values_circle_center_type',
71 [
72 'label' => esc_html__('Type', 'king-addons'),
73 'type' => Controls_Manager::SELECT,
74 'default' => 'image',
75 'options' => [
76 'image' => esc_html__('Image', 'king-addons'),
77 'lottie' => esc_html__('Lottie Animation', 'king-addons'),
78 ],
79 ]
80 );
81
82 // ── Image ─────────────────────────────────────────────────────────
83 $this->add_control(
84 'ka_values_circle_image',
85 [
86 'label' => esc_html__('Image', 'king-addons'),
87 'type' => Controls_Manager::MEDIA,
88 'default' => ['url' => ''],
89 'condition' => ['ka_values_circle_center_type' => 'image'],
90 ]
91 );
92
93 // ── Lottie ────────────────────────────────────────────────────────
94 $this->add_control(
95 'ka_values_circle_lottie_source',
96 [
97 'label' => esc_html__('Lottie File Source', 'king-addons'),
98 'type' => Controls_Manager::SELECT,
99 'options' => [
100 'file' => esc_html__('Media File (JSON)', 'king-addons'),
101 'url' => esc_html__('External URL', 'king-addons'),
102 ],
103 'default' => 'file',
104 'condition' => ['ka_values_circle_center_type' => 'lottie'],
105 ]
106 );
107
108 $this->add_control(
109 'ka_values_circle_lottie_file',
110 [
111 'label' => esc_html__('Upload JSON File', 'king-addons'),
112 'type' => Controls_Manager::MEDIA,
113 'media_type' => 'application/json',
114 'condition' => [
115 'ka_values_circle_center_type' => 'lottie',
116 'ka_values_circle_lottie_source' => 'file',
117 ],
118 ]
119 );
120
121 $this->add_control(
122 'ka_values_circle_lottie_url',
123 [
124 'label' => esc_html__('Animation JSON URL', 'king-addons'),
125 'type' => Controls_Manager::TEXT,
126 'label_block' => true,
127 'dynamic' => ['active' => true],
128 'description' => esc_html__('Get free animations at lottiefiles.com', 'king-addons'),
129 'condition' => [
130 'ka_values_circle_center_type' => 'lottie',
131 'ka_values_circle_lottie_source' => 'url',
132 ],
133 ]
134 );
135
136 $this->add_control(
137 'ka_values_circle_lottie_autoplay',
138 [
139 'label' => esc_html__('Autoplay', 'king-addons'),
140 'type' => Controls_Manager::SWITCHER,
141 'default' => 'yes',
142 'return_value' => 'yes',
143 'separator' => 'before',
144 'condition' => ['ka_values_circle_center_type' => 'lottie'],
145 ]
146 );
147
148 $this->add_control(
149 'ka_values_circle_lottie_loop',
150 [
151 'label' => esc_html__('Loop', 'king-addons'),
152 'type' => Controls_Manager::SWITCHER,
153 'default' => 'yes',
154 'return_value' => 'yes',
155 'condition' => ['ka_values_circle_center_type' => 'lottie'],
156 ]
157 );
158
159 $this->add_control(
160 'ka_values_circle_lottie_speed',
161 [
162 'label' => esc_html__('Speed', 'king-addons'),
163 'type' => Controls_Manager::NUMBER,
164 'default' => 1,
165 'min' => 0.1,
166 'max' => 3,
167 'step' => 0.1,
168 'condition' => ['ka_values_circle_center_type' => 'lottie'],
169 ]
170 );
171
172 $this->add_control(
173 'ka_values_circle_lottie_reverse',
174 [
175 'label' => esc_html__('Reverse', 'king-addons'),
176 'type' => Controls_Manager::SWITCHER,
177 'return_value' => 'yes',
178 'condition' => ['ka_values_circle_center_type' => 'lottie'],
179 ]
180 );
181
182 $this->add_control(
183 'ka_values_circle_lottie_renderer',
184 [
185 'label' => esc_html__('Render As', 'king-addons'),
186 'type' => Controls_Manager::SELECT,
187 'options' => [
188 'svg' => 'SVG',
189 'canvas' => 'Canvas',
190 'html' => 'HTML',
191 ],
192 'default' => 'svg',
193 'condition' => ['ka_values_circle_center_type' => 'lottie'],
194 ]
195 );
196
197 $this->add_responsive_control(
198 'ka_values_circle_image_width',
199 [
200 'label' => esc_html__('Width', 'king-addons'),
201 'type' => Controls_Manager::SLIDER,
202 'size_units' => ['%', 'px'],
203 'range' => [
204 '%' => ['min' => 5, 'max' => 90, 'step' => 1],
205 'px' => ['min' => 50, 'max' => 800, 'step' => 1],
206 ],
207 'default' => ['unit' => '%', 'size' => 40],
208 'selectors' => [
209 '{{WRAPPER}} .king-addons-values-circle-center-image-wrap' => 'width: {{SIZE}}{{UNIT}};',
210 '{{WRAPPER}} .king-addons-values-circle-mobile-image' => 'width: {{SIZE}}{{UNIT}};',
211 ],
212 ]
213 );
214
215 $this->end_controls_section();
216
217 // ── Style: Mobile Layout ───────────────────────────────────────
218 $this->start_controls_section(
219 'ka_values_circle_mobile_layout_style',
220 [
221 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Mobile Layout', 'king-addons'),
222 'tab' => Controls_Manager::TAB_STYLE,
223 ]
224 );
225
226 $this->add_responsive_control(
227 'ka_values_circle_mobile_gap_image_to_first',
228 [
229 'label' => esc_html__('Image → First Block Gap', 'king-addons'),
230 'type' => Controls_Manager::SLIDER,
231 'size_units' => ['px'],
232 'range' => ['px' => ['min' => 12, 'max' => 220, 'step' => 1]],
233 'default' => ['unit' => 'px', 'size' => 50],
234 'selectors' => [
235 '{{WRAPPER}} .king-addons-values-circle-mobile-view .ka-vcm-connector--first' => 'height: {{SIZE}}{{UNIT}};',
236 ],
237 ]
238 );
239
240 $this->add_responsive_control(
241 'ka_values_circle_mobile_gap_between_blocks',
242 [
243 'label' => esc_html__('Gap Between Blocks', 'king-addons'),
244 'type' => Controls_Manager::SLIDER,
245 'size_units' => ['px'],
246 'range' => ['px' => ['min' => 12, 'max' => 220, 'step' => 1]],
247 'default' => ['unit' => 'px', 'size' => 50],
248 'selectors' => [
249 '{{WRAPPER}} .king-addons-values-circle-mobile-view .ka-vcm-connector--between' => 'height: {{SIZE}}{{UNIT}};',
250 ],
251 ]
252 );
253
254 $this->add_control(
255 'ka_values_circle_mobile_conn_gap',
256 [
257 'label' => esc_html__('Gap from block edge (px)', 'king-addons'),
258 'type' => Controls_Manager::SLIDER,
259 'size_units' => ['px'],
260 'range' => ['px' => ['min' => 0, 'max' => 40, 'step' => 1]],
261 'default' => ['unit' => 'px', 'size' => 6],
262 'separator' => 'before',
263 ]
264 );
265
266 $this->add_control(
267 'ka_values_circle_mobile_dot_r_small',
268 [
269 'label' => esc_html__('Small dot radius (px)', 'king-addons'),
270 'type' => Controls_Manager::SLIDER,
271 'size_units' => ['px'],
272 'range' => ['px' => ['min' => 1, 'max' => 30, 'step' => 0.5]],
273 'default' => ['unit' => 'px', 'size' => 5.5],
274 'separator' => 'before',
275 ]
276 );
277
278 $this->add_control(
279 'ka_values_circle_mobile_dot_r_large',
280 [
281 'label' => esc_html__('Large dot radius (px)', 'king-addons'),
282 'type' => Controls_Manager::SLIDER,
283 'size_units' => ['px'],
284 'range' => ['px' => ['min' => 1, 'max' => 40, 'step' => 0.5]],
285 'default' => ['unit' => 'px', 'size' => 8],
286 ]
287 );
288
289 $this->add_control(
290 'ka_values_circle_mobile_dot_step',
291 [
292 'label' => esc_html__('Spacing between dots (px)', 'king-addons'),
293 'type' => Controls_Manager::SLIDER,
294 'size_units' => ['px'],
295 'range' => ['px' => ['min' => 2, 'max' => 80, 'step' => 1]],
296 'default' => ['unit' => 'px', 'size' => 28],
297 'separator' => 'before',
298 ]
299 );
300
301 $this->end_controls_section();
302
303 // ── Content: Items ─────────────────────────────────────────────
304 $items_config = [
305 ['top_left', 'top-left', esc_html__('Top Left', 'king-addons'), 'left', 60, 'top', 10, 'Respect', "Honouring culture,\npeople, and\npartnerships"],
306 ['top_right', 'top-right', esc_html__('Top Right', 'king-addons'), 'right', 60, 'top', 10, 'Sustainability',"Extending\nproduct life\ncycles"],
307 ['middle_left', 'middle-left', esc_html__('Middle Left', 'king-addons'), 'left', -24, 'top', 286, 'Integrity', "Acting with\nhonesty and\naccountability"],
308 ['middle_right', 'middle-right', esc_html__('Middle Right', 'king-addons'), 'right', -24, 'top', 286, 'Excellence', "Delivering quality\nand reliability\nevery time"],
309 ['bottom_left', 'bottom-left', esc_html__('Bottom Left', 'king-addons'), 'left', 60, 'bottom', 10, 'Safety', "We put safety first\n- protecting our\npeople, partners,\nand environment"],
310 ['bottom_right', 'bottom-right', esc_html__('Bottom Right', 'king-addons'), 'right', 60, 'bottom', 10, 'Inclusion', "Empowering\nAboriginal\nparticipation\nand growth"],
311 ];
312
313 foreach ($items_config as [$prefix, $slot, $label, $h_prop, $h_default, $v_prop, $v_default, $default_title, $default_desc]) {
314 $this->add_item_section($prefix, $slot, $label, $h_prop, $h_default, $v_prop, $v_default, $default_title, $default_desc);
315 }
316
317 // ── Style: Connectors ───────────────────────────────────────────
318 $this->start_controls_section(
319 'ka_values_circle_connectors_style',
320 [
321 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Connectors', 'king-addons'),
322 'tab' => Controls_Manager::TAB_STYLE,
323 ]
324 );
325
326 $this->add_control(
327 'ka_values_circle_dot_color',
328 [
329 'label' => esc_html__('Dot Color', 'king-addons'),
330 'type' => Controls_Manager::COLOR,
331 'default' => '#f2e3b8',
332 'selectors' => [
333 '{{WRAPPER}} .ka-values-circle-dot' => 'fill: {{VALUE}};',
334 ],
335 ]
336 );
337
338 $this->add_control(
339 'ka_values_circle_conn_gap',
340 [
341 'label' => esc_html__('Gap from block edge (px)', 'king-addons'),
342 'type' => Controls_Manager::SLIDER,
343 'size_units' => ['px'],
344 'range' => ['px' => ['min' => 0, 'max' => 80, 'step' => 1]],
345 'default' => ['unit' => 'px', 'size' => 20],
346 ]
347 );
348
349 $this->add_control(
350 'ka_values_circle_dot_r_small',
351 [
352 'label' => esc_html__('Small dot radius (px)', 'king-addons'),
353 'type' => Controls_Manager::SLIDER,
354 'size_units' => ['px'],
355 'range' => ['px' => ['min' => 1, 'max' => 30, 'step' => 0.5]],
356 'default' => ['unit' => 'px', 'size' => 8],
357 'separator' => 'before',
358 ]
359 );
360
361 $this->add_control(
362 'ka_values_circle_dot_r_large',
363 [
364 'label' => esc_html__('Large dot radius (px)', 'king-addons'),
365 'type' => Controls_Manager::SLIDER,
366 'size_units' => ['px'],
367 'range' => ['px' => ['min' => 1, 'max' => 40, 'step' => 0.5]],
368 'default' => ['unit' => 'px', 'size' => 9.5],
369 ]
370 );
371
372 $this->end_controls_section();
373
374 // ── Style: Per-connector ──────────────────────────────────────────
375 $this->add_connector_section('top', esc_html__('Top', 'king-addons'), 12);
376 $this->add_connector_section('bottom', esc_html__('Bottom', 'king-addons'), 12);
377 $this->add_connector_section('left_top', esc_html__('Left Top', 'king-addons'), 18);
378 $this->add_connector_section('left_bottom', esc_html__('Left Bottom', 'king-addons'), 18);
379 $this->add_connector_section('right_top', esc_html__('Right Top', 'king-addons'), 18);
380 $this->add_connector_section('right_bottom', esc_html__('Right Bottom', 'king-addons'), 18);
381
382 // ── Style: Text Blocks ───────────────────────────────────────────
383 $this->start_controls_section(
384 'ka_values_circle_blocks_style',
385 [
386 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Text Blocks', 'king-addons'),
387 'tab' => Controls_Manager::TAB_STYLE,
388 ]
389 );
390
391 $this->add_responsive_control(
392 'ka_values_circle_block_width',
393 [
394 'label' => esc_html__('Width', 'king-addons'),
395 'type' => Controls_Manager::SLIDER,
396 'size_units' => ['px', '%', 'vw'],
397 'range' => [
398 'px' => ['min' => 80, 'max' => 500, 'step' => 1],
399 '%' => ['min' => 5, 'max' => 60, 'step' => 1],
400 'vw' => ['min' => 5, 'max' => 40, 'step' => 0.5],
401 ],
402 'default' => ['unit' => 'px', 'size' => 200],
403 'selectors' => [
404 '{{WRAPPER}} .king-addons-values-circle-item' => 'width: {{SIZE}}{{UNIT}};',
405 ],
406 ]
407 );
408
409 $this->end_controls_section();
410
411 // ── Style: Title Typography ──────────────────────────────────────
412 $this->start_controls_section(
413 'ka_values_circle_title_style',
414 [
415 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Title', 'king-addons'),
416 'tab' => Controls_Manager::TAB_STYLE,
417 ]
418 );
419
420 $this->add_control(
421 'ka_values_circle_title_color',
422 [
423 'label' => esc_html__('Color', 'king-addons'),
424 'type' => Controls_Manager::COLOR,
425 'selectors' => [
426 '{{WRAPPER}} .king-addons-values-circle-title' => 'color: {{VALUE}};',
427 ],
428 ]
429 );
430
431 $this->add_group_control(
432 Group_Control_Typography::get_type(),
433 [
434 'name' => 'ka_values_circle_title_typography',
435 'selector' => '{{WRAPPER}} .king-addons-values-circle-title',
436 ]
437 );
438
439 $this->end_controls_section();
440
441 // ── Style: Divider ─────────────────────────────────────────────
442 $this->start_controls_section(
443 'ka_values_circle_divider_style',
444 [
445 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Divider', 'king-addons'),
446 'tab' => Controls_Manager::TAB_STYLE,
447 ]
448 );
449
450 $this->add_control(
451 'ka_values_circle_divider_color',
452 [
453 'label' => esc_html__('Color', 'king-addons'),
454 'type' => Controls_Manager::COLOR,
455 'default' => '#8f8f8f',
456 'selectors' => [
457 '{{WRAPPER}} .king-addons-values-circle-divider' => 'border-color: {{VALUE}};',
458 ],
459 ]
460 );
461
462 $this->add_responsive_control(
463 'ka_values_circle_divider_width',
464 [
465 'label' => esc_html__('Width', 'king-addons'),
466 'type' => Controls_Manager::SLIDER,
467 'size_units' => ['px', '%'],
468 'range' => [
469 'px' => ['min' => 10, 'max' => 300, 'step' => 1],
470 '%' => ['min' => 5, 'max' => 100, 'step' => 1],
471 ],
472 'default' => ['unit' => 'px', 'size' => 130],
473 'selectors' => [
474 '{{WRAPPER}} .king-addons-values-circle-divider' => 'width: {{SIZE}}{{UNIT}};',
475 ],
476 ]
477 );
478
479 $this->add_control(
480 'ka_values_circle_divider_thickness',
481 [
482 'label' => esc_html__('Thickness (px)', 'king-addons'),
483 'type' => Controls_Manager::SLIDER,
484 'size_units' => ['px'],
485 'range' => ['px' => ['min' => 1, 'max' => 10, 'step' => 0.5]],
486 'default' => ['unit' => 'px', 'size' => 1.5],
487 'selectors' => [
488 '{{WRAPPER}} .king-addons-values-circle-divider' => 'border-top-width: {{SIZE}}{{UNIT}};',
489 ],
490 ]
491 );
492
493 $this->add_responsive_control(
494 'ka_values_circle_divider_spacing',
495 [
496 'label' => esc_html__('Spacing (top / bottom)', 'king-addons'),
497 'type' => Controls_Manager::DIMENSIONS,
498 'size_units' => ['px'],
499 'default' => [
500 'top' => '8',
501 'bottom' => '10',
502 'unit' => 'px',
503 'isLinked' => false,
504 ],
505 'selectors' => [
506 '{{WRAPPER}} .king-addons-values-circle-divider' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
507 ],
508 ]
509 );
510
511 $this->end_controls_section();
512
513 // ── Style: Description Typography ─────────────────────────────────
514 $this->start_controls_section(
515 'ka_values_circle_description_style',
516 [
517 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Description', 'king-addons'),
518 'tab' => Controls_Manager::TAB_STYLE,
519 ]
520 );
521
522 $this->add_control(
523 'ka_values_circle_description_color',
524 [
525 'label' => esc_html__('Color', 'king-addons'),
526 'type' => Controls_Manager::COLOR,
527 'selectors' => [
528 '{{WRAPPER}} .king-addons-values-circle-description' => 'color: {{VALUE}};',
529 ],
530 ]
531 );
532
533 $this->add_group_control(
534 Group_Control_Typography::get_type(),
535 [
536 'name' => 'ka_values_circle_description_typography',
537 'selector' => '{{WRAPPER}} .king-addons-values-circle-description',
538 ]
539 );
540
541 $this->end_controls_section();
542 }
543
544 private function add_item_section(
545 string $prefix,
546 string $slot,
547 string $label,
548 string $h_prop,
549 int $h_default,
550 string $v_prop,
551 int $v_default,
552 string $default_title,
553 string $default_desc
554 ): void {
555 $sid = str_replace('-', '_', $slot);
556 $selector = '{{WRAPPER}} .king-addons-values-circle-item--' . $slot;
557
558 $this->start_controls_section(
559 'ka_values_circle_section_' . $prefix,
560 [
561 'label' => KING_ADDONS_ELEMENTOR_ICON . $label,
562 'tab' => Controls_Manager::TAB_CONTENT,
563 ]
564 );
565
566 // ── Text ───────────────────────────────────────────────────────
567 $this->add_control(
568 'ka_values_circle_' . $prefix . '_title',
569 [
570 'label' => esc_html__('Title', 'king-addons'),
571 'type' => Controls_Manager::TEXT,
572 'default' => $default_title,
573 'label_block' => true,
574 ]
575 );
576
577 $this->add_control(
578 'ka_values_circle_' . $prefix . '_description',
579 [
580 'label' => esc_html__('Description', 'king-addons'),
581 'type' => Controls_Manager::TEXTAREA,
582 'default' => $default_desc,
583 ]
584 );
585
586 // ── Position ──────────────────────────────────────────────────
587 $this->add_control(
588 'ka_values_circle_' . $prefix . '_pos_heading',
589 [
590 'label' => esc_html__('Position', 'king-addons'),
591 'type' => Controls_Manager::HEADING,
592 'separator' => 'before',
593 ]
594 );
595
596 $this->add_responsive_control(
597 'ka_values_circle_pos_' . $sid . '_x',
598 [
599 'label' => esc_html__('Horizontal offset', 'king-addons'),
600 'type' => Controls_Manager::SLIDER,
601 'size_units' => ['px'],
602 'range' => ['px' => ['min' => -260, 'max' => 260, 'step' => 1]],
603 'default' => ['unit' => 'px', 'size' => $h_default],
604 'selectors' => [$selector => $h_prop . ': {{SIZE}}{{UNIT}};'],
605 ]
606 );
607
608 $this->add_responsive_control(
609 'ka_values_circle_pos_' . $sid . '_y',
610 [
611 'label' => esc_html__('Vertical offset', 'king-addons'),
612 'type' => Controls_Manager::SLIDER,
613 'size_units' => ['px'],
614 'range' => ['px' => ['min' => -40, 'max' => 860, 'step' => 1]],
615 'default' => ['unit' => 'px', 'size' => $v_default],
616 'selectors' => [$selector => $v_prop . ': {{SIZE}}{{UNIT}};'],
617 ]
618 );
619
620 $this->end_controls_section();
621 }
622
623 private function add_connector_section(string $id, string $label, int $default_bend): void
624 {
625 $key = str_replace('-', '_', $id);
626 $hid = str_replace('_', '-', $id);
627
628 $this->start_controls_section(
629 'ka_values_circle_conn_style_' . $key,
630 [
631 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Connector: ', 'king-addons') . $label,
632 'tab' => Controls_Manager::TAB_STYLE,
633 ]
634 );
635
636 $this->add_control(
637 'ka_conn_' . $key . '_bend',
638 [
639 'label' => esc_html__('Bend (px)', 'king-addons'),
640 'type' => Controls_Manager::SLIDER,
641 'size_units' => ['px'],
642 'range' => ['px' => ['min' => 0, 'max' => 160, 'step' => 1]],
643 'default' => ['unit' => 'px', 'size' => $default_bend],
644 ]
645 );
646
647 $this->add_control(
648 'ka_conn_' . $key . '_start_x',
649 [
650 'label' => esc_html__('Start X offset (px)', 'king-addons'),
651 'type' => Controls_Manager::SLIDER,
652 'size_units' => ['px'],
653 'range' => ['px' => ['min' => -200, 'max' => 200, 'step' => 1]],
654 'default' => ['unit' => 'px', 'size' => 0],
655 ]
656 );
657
658 $this->add_control(
659 'ka_conn_' . $key . '_start_y',
660 [
661 'label' => esc_html__('Start Y offset (px)', 'king-addons'),
662 'type' => Controls_Manager::SLIDER,
663 'size_units' => ['px'],
664 'range' => ['px' => ['min' => -200, 'max' => 200, 'step' => 1]],
665 'default' => ['unit' => 'px', 'size' => 0],
666 ]
667 );
668
669 $this->add_control(
670 'ka_conn_' . $key . '_end_x',
671 [
672 'label' => esc_html__('End X offset (px)', 'king-addons'),
673 'type' => Controls_Manager::SLIDER,
674 'size_units' => ['px'],
675 'range' => ['px' => ['min' => -200, 'max' => 200, 'step' => 1]],
676 'default' => ['unit' => 'px', 'size' => 0],
677 ]
678 );
679
680 $this->add_control(
681 'ka_conn_' . $key . '_end_y',
682 [
683 'label' => esc_html__('End Y offset (px)', 'king-addons'),
684 'type' => Controls_Manager::SLIDER,
685 'size_units' => ['px'],
686 'range' => ['px' => ['min' => -200, 'max' => 200, 'step' => 1]],
687 'default' => ['unit' => 'px', 'size' => 0],
688 ]
689 );
690
691 $this->end_controls_section();
692 }
693
694 protected function render(): void
695 {
696 $settings = $this->get_settings_for_display();
697
698 $gap = (float) ($settings['ka_values_circle_conn_gap']['size'] ?? 20);
699 $r_small = (float) ($settings['ka_values_circle_dot_r_small']['size'] ?? 5);
700 $r_large = (float) ($settings['ka_values_circle_dot_r_large']['size'] ?? 9.5);
701 $mob_r_small = (float) ($settings['ka_values_circle_mobile_dot_r_small']['size'] ?? 5.5);
702 $mob_r_large = (float) ($settings['ka_values_circle_mobile_dot_r_large']['size'] ?? 8);
703 $mob_conn_gap = (float) ($settings['ka_values_circle_mobile_conn_gap']['size'] ?? 6);
704 $mob_dot_step = (float) ($settings['ka_values_circle_mobile_dot_step']['size'] ?? 28);
705
706 $conn_ids = ['top', 'bottom', 'left_top', 'left_bottom', 'right_top', 'right_bottom'];
707 $conn_defaults = ['top' => 12, 'bottom' => 12, 'left_top' => 18, 'left_bottom' => 18, 'right_top' => 18, 'right_bottom' => 18];
708 $conn_attrs = '';
709 foreach ($conn_ids as $cid) {
710 $hid = str_replace('_', '-', $cid);
711 $bend = (float) ($settings['ka_conn_' . $cid . '_bend']['size'] ?? $conn_defaults[$cid]);
712 $start_x = (float) ($settings['ka_conn_' . $cid . '_start_x']['size'] ?? 0);
713 $start_y = (float) ($settings['ka_conn_' . $cid . '_start_y']['size'] ?? 0);
714 $end_x = (float) ($settings['ka_conn_' . $cid . '_end_x']['size'] ?? 0);
715 $end_y = (float) ($settings['ka_conn_' . $cid . '_end_y']['size'] ?? 0);
716 $conn_attrs .= sprintf(
717 ' data-conn-%1$s-bend="%2$s" data-conn-%1$s-start-x="%3$s" data-conn-%1$s-start-y="%4$s" data-conn-%1$s-end-x="%5$s" data-conn-%1$s-end-y="%6$s"',
718 esc_attr($hid),
719 esc_attr($bend),
720 esc_attr($start_x),
721 esc_attr($start_y),
722 esc_attr($end_x),
723 esc_attr($end_y)
724 );
725 }
726
727 $items = [
728 ['slot' => 'top-left', 'prefix' => 'top_left'],
729 ['slot' => 'top-right', 'prefix' => 'top_right'],
730 ['slot' => 'middle-left', 'prefix' => 'middle_left'],
731 ['slot' => 'middle-right', 'prefix' => 'middle_right'],
732 ['slot' => 'bottom-left', 'prefix' => 'bottom_left'],
733 ['slot' => 'bottom-right', 'prefix' => 'bottom_right'],
734 ];
735
736 foreach ($items as &$item) {
737 $p = $item['prefix'];
738 $item['title'] = (string) ($settings['ka_values_circle_' . $p . '_title'] ?? '');
739 $item['description'] = (string) ($settings['ka_values_circle_' . $p . '_description'] ?? '');
740 }
741 unset($item);
742
743 // ── Centre-image vars (used in both desktop and mobile views) ──────────
744 $center_type = $settings['ka_values_circle_center_type'] ?? 'image';
745 $center_img = $settings['ka_values_circle_image'] ?? [];
746 $lottie_json = '';
747 $lottie_cfg = '';
748 if ($center_type === 'lottie') {
749 $lottie_source = $settings['ka_values_circle_lottie_source'] ?? 'file';
750 $lottie_json = ($lottie_source === 'url')
751 ? esc_url($settings['ka_values_circle_lottie_url'] ?? '')
752 : esc_url($settings['ka_values_circle_lottie_file']['url'] ?? '');
753 $lottie_json = $lottie_json ?: KING_ADDONS_URL . 'includes/assets/libraries/lottie/default.json';
754 $lottie_cfg = esc_attr(json_encode([
755 'autoplay' => $settings['ka_values_circle_lottie_autoplay'] ?? 'yes',
756 'loop' => $settings['ka_values_circle_lottie_loop'] ?? 'yes',
757 'speed' => (float) ($settings['ka_values_circle_lottie_speed'] ?? 1),
758 'renderer' => $settings['ka_values_circle_lottie_renderer'] ?? 'svg',
759 'reverse' => $settings['ka_values_circle_lottie_reverse'] ?? '',
760 ]));
761 }
762
763 ?>
764 <div class="king-addons-values-circle-wrap"
765 data-conn-gap="<?php echo esc_attr($gap); ?>"
766 data-dot-r-small="<?php echo esc_attr($r_small); ?>"
767 data-dot-r-large="<?php echo esc_attr($r_large); ?>"
768 data-mobile-dot-r-small="<?php echo esc_attr($mob_r_small); ?>"
769 data-mobile-dot-r-large="<?php echo esc_attr($mob_r_large); ?>"
770 data-mobile-conn-gap="<?php echo esc_attr($mob_conn_gap); ?>"
771 data-mobile-dot-step="<?php echo esc_attr($mob_dot_step); ?>"
772 <?php echo $conn_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped above ?>>
773 <div class="king-addons-values-circle-center-image-wrap">
774 <?php if ($center_type === 'lottie') : ?>
775 <div class="king-addons-values-circle-lottie"
776 data-settings="<?php echo $lottie_cfg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped ?>"
777 data-json-url="<?php echo esc_url($lottie_json); ?>"
778 aria-hidden="true"></div>
779 <?php elseif ($center_type === 'image' && !empty($center_img['url'])) : ?>
780 <img src="<?php echo esc_url($center_img['url']); ?>"
781 alt=""
782 loading="lazy">
783 <?php else : ?>
784 <div class="king-addons-values-circle-image-placeholder" aria-hidden="true"></div>
785 <?php endif; ?>
786 </div>
787 <div class="king-addons-values-circle-svg-layer" aria-hidden="true">
788 <svg viewBox="0 0 1000 860" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg">
789 <g class="ka-values-circle-connectors ka-values-circle-connectors-dynamic"></g>
790 </svg>
791 </div>
792
793 <?php foreach ($items as $item) : ?>
794 <div class="king-addons-values-circle-item king-addons-values-circle-item--<?php echo esc_attr($item['slot']); ?>">
795 <h3 class="king-addons-values-circle-title"><?php echo esc_html($item['title']); ?></h3>
796 <span class="king-addons-values-circle-divider" aria-hidden="true"></span>
797 <div class="king-addons-values-circle-description"><?php echo wp_kses_post(nl2br(esc_html($item['description']))); ?></div>
798 </div>
799 <?php endforeach; ?>
800
801 <?php // ── Mobile-only vertical strip ────────────────────────────────── ?>
802 <div class="king-addons-values-circle-mobile-view">
803
804 <?php // Centre image at the top ?>
805 <div class="king-addons-values-circle-mobile-image">
806 <?php if ($center_type === 'lottie') : ?>
807 <div class="king-addons-values-circle-lottie"
808 data-settings="<?php echo $lottie_cfg; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped ?>"
809 data-json-url="<?php echo esc_url($lottie_json); ?>"
810 aria-hidden="true"></div>
811 <?php elseif ($center_type === 'image' && !empty($center_img['url'])) : ?>
812 <img src="<?php echo esc_url($center_img['url']); ?>" alt="" loading="lazy">
813 <?php else : ?>
814 <div class="king-addons-values-circle-image-placeholder" aria-hidden="true"></div>
815 <?php endif; ?>
816 </div>
817
818 <?php foreach ($items as $idx => $item) :
819 $conn_class = ($idx === 0) ? 'ka-vcm-connector--first' : 'ka-vcm-connector--between';
820 ?>
821 <svg class="ka-vcm-connector <?php echo esc_attr($conn_class); ?>" viewBox="0 0 100 60"
822 xmlns="http://www.w3.org/2000/svg"
823 aria-hidden="true" focusable="false">
824 <g class="ka-vcm-dots ka-values-circle-connectors"></g>
825 </svg>
826 <div class="king-addons-values-circle-mobile-card">
827 <h3 class="king-addons-values-circle-title"><?php echo esc_html($item['title']); ?></h3>
828 <span class="king-addons-values-circle-divider" aria-hidden="true"></span>
829 <div class="king-addons-values-circle-description"><?php echo wp_kses_post(nl2br(esc_html($item['description']))); ?></div>
830 </div>
831 <?php endforeach; ?>
832
833 </div><!-- /.king-addons-values-circle-mobile-view -->
834
835 </div>
836 <?php
837 }
838 }
839