PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.63
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.63
51.1.86 51.1.84 51.1.85 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 All 40 releases
king-addons / includes / widgets / Scroll_Story_Sections / Scroll_Story_Sections.php

Scroll_Story_Sections.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.63, at includes/widgets/Scroll_Story_Sections/Scroll_Story_Sections.php

1,652 lines 58.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Scroll Story Sections Widget.
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\Repeater;
18 use Elementor\Widget_Base;
19
20 if (!defined('ABSPATH')) {
21 exit; // Exit if accessed directly.
22 }
23
24 class Scroll_Story_Sections extends Widget_Base
25 {
26 public function get_name(): string
27 {
28 return 'king-addons-scroll-story-sections';
29 }
30
31 public function get_title(): string
32 {
33 return esc_html__('Scroll Story Sections', 'king-addons');
34 }
35
36 public function get_icon(): string
37 {
38 return 'eicon-scroll';
39 }
40
41 public function get_style_depends(): array
42 {
43 return [
44 KING_ADDONS_ASSETS_UNIQUE_KEY . '-scroll-story-sections-style',
45 'elementor-icons-fa-solid',
46 'elementor-icons-fa-regular',
47 'elementor-icons-fa-brands',
48 ];
49 }
50
51 public function get_script_depends(): array
52 {
53 return [
54 KING_ADDONS_ASSETS_UNIQUE_KEY . '-scroll-story-sections-script',
55 ];
56 }
57
58 public function get_categories(): array
59 {
60 return ['king-addons'];
61 }
62
63 public function get_keywords(): array
64 {
65 return ['scroll', 'story', 'steps', 'timeline', 'narrative', 'sections', 'king-addons'];
66 }
67
68 public function get_custom_help_url()
69 {
70 return 'mailto:[email protected]?subject=Bug Report - King Addons&body=Please describe the issue';
71 }
72
73 protected function register_controls(): void
74 {
75 $this->register_layout_controls();
76 $this->register_steps_controls();
77 $this->register_behavior_controls();
78 $this->register_pro_controls();
79 $this->register_style_container_controls();
80 $this->register_style_steps_controls();
81 $this->register_style_content_controls();
82 $this->register_style_media_controls();
83 $this->register_pro_notice_controls();
84 }
85
86 protected function register_layout_controls(): void
87 {
88 $this->start_controls_section(
89 'kng_scroll_story_layout_section',
90 [
91 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Layout', 'king-addons'),
92 'tab' => Controls_Manager::TAB_CONTENT,
93 ]
94 );
95
96 $this->add_control(
97 'kng_scroll_story_layout',
98 [
99 'label' => esc_html__('Layout', 'king-addons'),
100 'type' => Controls_Manager::SELECT,
101 'default' => 'normal',
102 'options' => [
103 'normal' => esc_html__('Two Columns', 'king-addons'),
104 'reversed' => esc_html__('Two Columns Reversed', 'king-addons'),
105 ],
106 'selectors_dictionary' => [
107 'normal' => 'flex-direction: row;',
108 'reversed' => 'flex-direction: row-reverse;',
109 ],
110 'selectors' => [
111 '{{WRAPPER}} .king-addons-scroll-story__grid' => '{{VALUE}}',
112 ],
113 'render_type' => 'template',
114 ]
115 );
116
117 $this->add_control(
118 'kng_scroll_story_columns_ratio',
119 [
120 'label' => esc_html__('Columns Ratio', 'king-addons'),
121 'type' => Controls_Manager::SELECT,
122 'default' => '40-60',
123 'options' => [
124 '40-60' => esc_html__('40 / 60', 'king-addons'),
125 '50-50' => esc_html__('50 / 50', 'king-addons'),
126 '60-40' => esc_html__('60 / 40', 'king-addons'),
127 ],
128 'selectors_dictionary' => [
129 '40-60' => '--kng-scroll-story-left: 40%; --kng-scroll-story-right: 60%;',
130 '50-50' => '--kng-scroll-story-left: 50%; --kng-scroll-story-right: 50%;',
131 '60-40' => '--kng-scroll-story-left: 60%; --kng-scroll-story-right: 40%;',
132 ],
133 'selectors' => [
134 '{{WRAPPER}} .king-addons-scroll-story' => '{{VALUE}}',
135 ],
136 'render_type' => 'template',
137 ]
138 );
139
140 $this->add_control(
141 'kng_scroll_story_vertical_align',
142 [
143 'label' => esc_html__('Vertical Align', 'king-addons'),
144 'type' => Controls_Manager::SELECT,
145 'default' => 'top',
146 'options' => [
147 'top' => esc_html__('Top', 'king-addons'),
148 'center' => esc_html__('Center', 'king-addons'),
149 ],
150 'selectors_dictionary' => [
151 'top' => 'align-items: flex-start;',
152 'center' => 'align-items: center;',
153 ],
154 'selectors' => [
155 '{{WRAPPER}} .king-addons-scroll-story__grid' => '{{VALUE}}',
156 ],
157 'render_type' => 'template',
158 ]
159 );
160
161 $this->add_responsive_control(
162 'kng_scroll_story_min_height',
163 [
164 'label' => esc_html__('Min Height', 'king-addons'),
165 'type' => Controls_Manager::SLIDER,
166 'size_units' => ['px', 'vh'],
167 'range' => [
168 'px' => [
169 'min' => 200,
170 'max' => 1200,
171 'step' => 10,
172 ],
173 'vh' => [
174 'min' => 20,
175 'max' => 100,
176 ],
177 ],
178 'selectors' => [
179 '{{WRAPPER}} .king-addons-scroll-story' => 'min-height: {{SIZE}}{{UNIT}};',
180 ],
181 ]
182 );
183
184 $this->end_controls_section();
185 }
186
187 protected function register_steps_controls(): void
188 {
189 $this->start_controls_section(
190 'kng_scroll_story_steps_section',
191 [
192 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Steps', 'king-addons'),
193 'tab' => Controls_Manager::TAB_CONTENT,
194 ]
195 );
196
197 $repeater = new Repeater();
198
199 $repeater->add_control(
200 'step_title',
201 [
202 'label' => esc_html__('Title', 'king-addons'),
203 'type' => Controls_Manager::TEXT,
204 'default' => esc_html__('Step Title', 'king-addons'),
205 'label_block' => true,
206 ]
207 );
208
209 $repeater->add_control(
210 'step_subtitle',
211 [
212 'label' => esc_html__('Subtitle', 'king-addons'),
213 'type' => Controls_Manager::TEXT,
214 'default' => '',
215 'label_block' => true,
216 ]
217 );
218
219 $repeater->add_control(
220 'step_description',
221 [
222 'label' => esc_html__('Description', 'king-addons'),
223 'type' => Controls_Manager::WYSIWYG,
224 'default' => esc_html__('Add a short description for this step.', 'king-addons'),
225 ]
226 );
227
228 $repeater->add_control(
229 'step_icon',
230 [
231 'label' => esc_html__('Icon', 'king-addons'),
232 'type' => Controls_Manager::ICONS,
233 'skin' => 'inline',
234 'label_block' => true,
235 ]
236 );
237
238 $repeater->add_control(
239 'step_media_type',
240 [
241 'label' => esc_html__('Media Type', 'king-addons'),
242 'type' => Controls_Manager::SELECT,
243 'default' => 'image',
244 'options' => [
245 'none' => esc_html__('None', 'king-addons'),
246 'image' => esc_html__('Image', 'king-addons'),
247 'video' => esc_html__('Video (Pro)', 'king-addons'),
248 'lottie' => esc_html__('Lottie (Pro)', 'king-addons'),
249 'template' => esc_html__('Template (Pro)', 'king-addons'),
250 ],
251 ]
252 );
253
254 Core::renderUpgradeProNotice($repeater, Controls_Manager::RAW_HTML, 'scroll-story-sections', 'step_media_type', ['video', 'lottie', 'template']);
255
256 $repeater->add_control(
257 'step_media_image',
258 [
259 'label' => esc_html__('Image', 'king-addons'),
260 'type' => Controls_Manager::MEDIA,
261 'condition' => [
262 'step_media_type' => 'image',
263 ],
264 ]
265 );
266
267 $repeater->add_group_control(
268 Group_Control_Image_Size::get_type(),
269 [
270 'name' => 'step_media_image_size',
271 'default' => 'large',
272 'condition' => [
273 'step_media_type' => 'image',
274 ],
275 ]
276 );
277
278 $repeater->add_control(
279 'step_cta_text',
280 [
281 'label' => esc_html__('CTA Text', 'king-addons'),
282 'type' => Controls_Manager::TEXT,
283 'default' => '',
284 'separator' => 'before',
285 ]
286 );
287
288 $repeater->add_control(
289 'step_cta_link',
290 [
291 'label' => esc_html__('CTA Link', 'king-addons'),
292 'type' => Controls_Manager::URL,
293 'placeholder' => esc_html__('https://your-link.com', 'king-addons'),
294 ]
295 );
296
297 $repeater->add_control(
298 'step_anchor_id',
299 [
300 'label' => esc_html__('Anchor ID (Pro)', 'king-addons'),
301 'type' => Controls_Manager::TEXT,
302 'classes' => $this->get_pro_control_class(),
303 'description' => esc_html__('Lowercase letters, numbers, dashes, or underscores only.', 'king-addons'),
304 ]
305 );
306
307 $this->add_control(
308 'kng_scroll_story_steps',
309 [
310 'label' => esc_html__('Steps', 'king-addons'),
311 'type' => Controls_Manager::REPEATER,
312 'fields' => $repeater->get_controls(),
313 'default' => $this->get_default_steps(),
314 'title_field' => '{{ step_title }}',
315 ]
316 );
317
318 $this->end_controls_section();
319 }
320
321 protected function register_behavior_controls(): void
322 {
323 $this->start_controls_section(
324 'kng_scroll_story_behavior_section',
325 [
326 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Behavior', 'king-addons'),
327 'tab' => Controls_Manager::TAB_CONTENT,
328 ]
329 );
330
331 $this->add_control(
332 'kng_scroll_story_steps_style',
333 [
334 'label' => esc_html__('Active Step Style', 'king-addons'),
335 'type' => Controls_Manager::SELECT,
336 'default' => 'minimal',
337 'options' => [
338 'minimal' => esc_html__('Minimal', 'king-addons'),
339 'highlighted' => esc_html__('Highlighted', 'king-addons'),
340 'card' => esc_html__('Card List', 'king-addons'),
341 ],
342 'prefix_class' => 'king-addons-scroll-story--preset-',
343 'render_type' => 'template',
344 ]
345 );
346
347 $this->add_control(
348 'kng_scroll_story_transition',
349 [
350 'label' => esc_html__('Content Transition', 'king-addons'),
351 'type' => Controls_Manager::SELECT,
352 'default' => 'fade',
353 'options' => [
354 'fade' => esc_html__('Fade', 'king-addons'),
355 'slide' => esc_html__('Slide', 'king-addons'),
356 'none' => esc_html__('None', 'king-addons'),
357 ],
358 'prefix_class' => 'king-addons-scroll-story--transition-',
359 'render_type' => 'template',
360 ]
361 );
362
363 $this->add_control(
364 'kng_scroll_story_transition_duration',
365 [
366 'label' => esc_html__('Transition Duration (ms)', 'king-addons'),
367 'type' => Controls_Manager::NUMBER,
368 'min' => 0,
369 'step' => 10,
370 'selectors' => [
371 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-transition-duration: {{VALUE}}ms; --kng-scroll-story-transition-duration-slide: {{VALUE}}ms;',
372 ],
373 ]
374 );
375
376 $this->add_control(
377 'kng_scroll_story_activation_offset',
378 [
379 'label' => esc_html__('Activation Offset (%)', 'king-addons'),
380 'type' => Controls_Manager::SLIDER,
381 'size_units' => ['%'],
382 'range' => [
383 '%' => [
384 'min' => 10,
385 'max' => 80,
386 ],
387 ],
388 'default' => [
389 'unit' => '%',
390 'size' => 40,
391 ],
392 ]
393 );
394
395 $this->add_control(
396 'kng_scroll_story_smooth_scroll',
397 [
398 'label' => esc_html__('Smooth Scroll on Click', 'king-addons'),
399 'type' => Controls_Manager::SWITCHER,
400 'return_value' => 'yes',
401 'default' => 'yes',
402 ]
403 );
404
405 $this->add_control(
406 'kng_scroll_story_scroll_duration',
407 [
408 'label' => esc_html__('Scroll Duration (ms)', 'king-addons'),
409 'type' => Controls_Manager::NUMBER,
410 'default' => 600,
411 'min' => 0,
412 'step' => 50,
413 'condition' => [
414 'kng_scroll_story_smooth_scroll' => 'yes',
415 ],
416 ]
417 );
418
419 $this->end_controls_section();
420 }
421
422 protected function register_pro_controls(): void
423 {
424 $this->start_controls_section(
425 'kng_scroll_story_sticky_section',
426 [
427 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Sticky Media (Pro)', 'king-addons'),
428 'tab' => Controls_Manager::TAB_CONTENT,
429 ]
430 );
431
432 $this->add_control(
433 'kng_scroll_story_sticky_enable',
434 [
435 'label' => esc_html__('Enable Sticky Media', 'king-addons'),
436 'type' => Controls_Manager::SWITCHER,
437 'return_value' => 'yes',
438 'classes' => $this->get_pro_control_class(),
439 ]
440 );
441
442 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'scroll-story-sections', 'kng_scroll_story_sticky_enable', ['yes']);
443
444 $this->add_control(
445 'kng_scroll_story_sticky_offset',
446 [
447 'label' => esc_html__('Sticky Top Offset (px)', 'king-addons'),
448 'type' => Controls_Manager::NUMBER,
449 'default' => 24,
450 'min' => 0,
451 'step' => 1,
452 'classes' => $this->get_pro_control_class(),
453 'condition' => [
454 'kng_scroll_story_sticky_enable' => 'yes',
455 ],
456 ]
457 );
458
459 $this->end_controls_section();
460
461 $this->start_controls_section(
462 'kng_scroll_story_progress_section',
463 [
464 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Progress (Pro)', 'king-addons'),
465 'tab' => Controls_Manager::TAB_CONTENT,
466 ]
467 );
468
469 $this->add_control(
470 'kng_scroll_story_progress_enable',
471 [
472 'label' => esc_html__('Enable Progress', 'king-addons'),
473 'type' => Controls_Manager::SWITCHER,
474 'return_value' => 'yes',
475 'classes' => $this->get_pro_control_class(),
476 ]
477 );
478
479 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'scroll-story-sections', 'kng_scroll_story_progress_enable', ['yes']);
480
481 $this->add_control(
482 'kng_scroll_story_progress_style',
483 [
484 'label' => esc_html__('Progress Style', 'king-addons'),
485 'type' => Controls_Manager::SELECT,
486 'default' => 'line-dots',
487 'options' => [
488 'line-dots' => esc_html__('Line + Dots', 'king-addons'),
489 'bar' => esc_html__('Bar', 'king-addons'),
490 'numeric' => esc_html__('Numeric', 'king-addons'),
491 ],
492 'classes' => $this->get_pro_control_class(),
493 'condition' => [
494 'kng_scroll_story_progress_enable' => 'yes',
495 ],
496 ]
497 );
498
499 $this->add_control(
500 'kng_scroll_story_progress_show_count',
501 [
502 'label' => esc_html__('Show Step Count', 'king-addons'),
503 'type' => Controls_Manager::SWITCHER,
504 'return_value' => 'yes',
505 'classes' => $this->get_pro_control_class(),
506 'condition' => [
507 'kng_scroll_story_progress_enable' => 'yes',
508 ],
509 ]
510 );
511
512 $this->end_controls_section();
513
514 $this->start_controls_section(
515 'kng_scroll_story_templates_section',
516 [
517 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Templates (Pro)', 'king-addons'),
518 'tab' => Controls_Manager::TAB_CONTENT,
519 ]
520 );
521
522 $this->add_control(
523 'kng_scroll_story_template_content',
524 [
525 'label' => esc_html__('Content Template ID', 'king-addons'),
526 'type' => Controls_Manager::NUMBER,
527 'min' => 0,
528 'classes' => $this->get_pro_control_class(),
529 ]
530 );
531
532 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'scroll-story-sections', 'kng_scroll_story_template_content', ['']);
533
534 $this->add_control(
535 'kng_scroll_story_template_media',
536 [
537 'label' => esc_html__('Media Template ID', 'king-addons'),
538 'type' => Controls_Manager::NUMBER,
539 'min' => 0,
540 'classes' => $this->get_pro_control_class(),
541 ]
542 );
543
544 $this->add_control(
545 'kng_scroll_story_template_per_step',
546 [
547 'label' => esc_html__('Template Per Step', 'king-addons'),
548 'type' => Controls_Manager::SWITCHER,
549 'return_value' => 'yes',
550 'classes' => $this->get_pro_control_class(),
551 ]
552 );
553
554 $this->end_controls_section();
555
556 $this->start_controls_section(
557 'kng_scroll_story_lottie_section',
558 [
559 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . esc_html__('Lottie (Pro)', 'king-addons'),
560 'tab' => Controls_Manager::TAB_CONTENT,
561 ]
562 );
563
564 $this->add_control(
565 'kng_scroll_story_lottie_source',
566 [
567 'label' => esc_html__('Source', 'king-addons'),
568 'type' => Controls_Manager::SELECT,
569 'default' => 'none',
570 'options' => [
571 'none' => esc_html__('None', 'king-addons'),
572 'url' => esc_html__('URL', 'king-addons'),
573 'media' => esc_html__('Media Library', 'king-addons'),
574 'json' => esc_html__('JSON String', 'king-addons'),
575 ],
576 'classes' => $this->get_pro_control_class(),
577 ]
578 );
579
580 Core::renderUpgradeProNotice($this, Controls_Manager::RAW_HTML, 'scroll-story-sections', 'kng_scroll_story_lottie_source', ['url', 'media', 'json']);
581
582 $this->add_control(
583 'kng_scroll_story_lottie_loop',
584 [
585 'label' => esc_html__('Loop', 'king-addons'),
586 'type' => Controls_Manager::SWITCHER,
587 'return_value' => 'yes',
588 'classes' => $this->get_pro_control_class(),
589 'condition' => [
590 'kng_scroll_story_lottie_source!' => 'none',
591 ],
592 ]
593 );
594
595 $this->add_control(
596 'kng_scroll_story_lottie_speed',
597 [
598 'label' => esc_html__('Playback Speed', 'king-addons'),
599 'type' => Controls_Manager::NUMBER,
600 'default' => 1,
601 'min' => 0.1,
602 'step' => 0.1,
603 'classes' => $this->get_pro_control_class(),
604 'condition' => [
605 'kng_scroll_story_lottie_source!' => 'none',
606 ],
607 ]
608 );
609
610 $this->add_control(
611 'kng_scroll_story_lottie_segment_start',
612 [
613 'label' => esc_html__('Segment Start Frame', 'king-addons'),
614 'type' => Controls_Manager::NUMBER,
615 'min' => 0,
616 'classes' => $this->get_pro_control_class(),
617 'condition' => [
618 'kng_scroll_story_lottie_source!' => 'none',
619 ],
620 ]
621 );
622
623 $this->add_control(
624 'kng_scroll_story_lottie_segment_end',
625 [
626 'label' => esc_html__('Segment End Frame', 'king-addons'),
627 'type' => Controls_Manager::NUMBER,
628 'min' => 0,
629 'classes' => $this->get_pro_control_class(),
630 'condition' => [
631 'kng_scroll_story_lottie_source!' => 'none',
632 ],
633 ]
634 );
635
636 $this->end_controls_section();
637 }
638
639 protected function register_style_container_controls(): void
640 {
641 $this->start_controls_section(
642 'kng_scroll_story_container_style',
643 [
644 'label' => esc_html__('Container', 'king-addons'),
645 'tab' => Controls_Manager::TAB_STYLE,
646 ]
647 );
648
649 $this->add_group_control(
650 Group_Control_Background::get_type(),
651 [
652 'name' => 'kng_scroll_story_container_background',
653 'selector' => '{{WRAPPER}} .king-addons-scroll-story',
654 ]
655 );
656
657 $this->add_responsive_control(
658 'kng_scroll_story_container_padding',
659 [
660 'label' => esc_html__('Padding', 'king-addons'),
661 'type' => Controls_Manager::DIMENSIONS,
662 'size_units' => ['px', '%', 'em', 'rem'],
663 'selectors' => [
664 '{{WRAPPER}} .king-addons-scroll-story__inner' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
665 ],
666 ]
667 );
668
669 $this->add_responsive_control(
670 'kng_scroll_story_column_gap',
671 [
672 'label' => esc_html__('Column Gap', 'king-addons'),
673 'type' => Controls_Manager::SLIDER,
674 'size_units' => ['px', 'rem'],
675 'range' => [
676 'px' => [
677 'min' => 0,
678 'max' => 120,
679 ],
680 'rem' => [
681 'min' => 0,
682 'max' => 6,
683 'step' => 0.25,
684 ],
685 ],
686 'selectors' => [
687 '{{WRAPPER}} .king-addons-scroll-story__grid' => 'gap: {{SIZE}}{{UNIT}};',
688 ],
689 ]
690 );
691
692 $this->add_responsive_control(
693 'kng_scroll_story_max_width',
694 [
695 'label' => esc_html__('Max Width', 'king-addons'),
696 'type' => Controls_Manager::SLIDER,
697 'size_units' => ['px', '%'],
698 'range' => [
699 'px' => [
700 'min' => 600,
701 'max' => 1800,
702 'step' => 10,
703 ],
704 '%' => [
705 'min' => 50,
706 'max' => 100,
707 ],
708 ],
709 'selectors' => [
710 '{{WRAPPER}} .king-addons-scroll-story__inner' => 'max-width: {{SIZE}}{{UNIT}}; margin-left: auto; margin-right: auto;',
711 ],
712 ]
713 );
714
715 $this->add_group_control(
716 Group_Control_Border::get_type(),
717 [
718 'name' => 'kng_scroll_story_container_border',
719 'selector' => '{{WRAPPER}} .king-addons-scroll-story',
720 ]
721 );
722
723 $this->add_responsive_control(
724 'kng_scroll_story_container_radius',
725 [
726 'label' => esc_html__('Border Radius', 'king-addons'),
727 'type' => Controls_Manager::DIMENSIONS,
728 'size_units' => ['px', '%'],
729 'selectors' => [
730 '{{WRAPPER}} .king-addons-scroll-story' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
731 ],
732 ]
733 );
734
735 $this->end_controls_section();
736 }
737
738 protected function register_style_steps_controls(): void
739 {
740 $this->start_controls_section(
741 'kng_scroll_story_steps_style',
742 [
743 'label' => esc_html__('Steps List', 'king-addons'),
744 'tab' => Controls_Manager::TAB_STYLE,
745 ]
746 );
747
748 $this->add_responsive_control(
749 'kng_scroll_story_steps_gap',
750 [
751 'label' => esc_html__('Item Spacing', 'king-addons'),
752 'type' => Controls_Manager::SLIDER,
753 'size_units' => ['px', 'rem'],
754 'range' => [
755 'px' => [
756 'min' => 0,
757 'max' => 60,
758 ],
759 'rem' => [
760 'min' => 0,
761 'max' => 4,
762 'step' => 0.25,
763 ],
764 ],
765 'selectors' => [
766 '{{WRAPPER}} .king-addons-scroll-story__steps' => 'gap: {{SIZE}}{{UNIT}};',
767 ],
768 ]
769 );
770
771 $this->add_responsive_control(
772 'kng_scroll_story_steps_icon_size',
773 [
774 'label' => esc_html__('Icon Size', 'king-addons'),
775 'type' => Controls_Manager::SLIDER,
776 'size_units' => ['px', 'em', 'rem'],
777 'range' => [
778 'px' => [
779 'min' => 8,
780 'max' => 48,
781 ],
782 'em' => [
783 'min' => 0.5,
784 'max' => 3,
785 'step' => 0.1,
786 ],
787 'rem' => [
788 'min' => 0.5,
789 'max' => 3,
790 'step' => 0.1,
791 ],
792 ],
793 'selectors' => [
794 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-icon-size: {{SIZE}}{{UNIT}};',
795 ],
796 ]
797 );
798
799 $this->add_responsive_control(
800 'kng_scroll_story_steps_icon_gap',
801 [
802 'label' => esc_html__('Icon Gap', 'king-addons'),
803 'type' => Controls_Manager::SLIDER,
804 'size_units' => ['px', 'em', 'rem'],
805 'range' => [
806 'px' => [
807 'min' => 0,
808 'max' => 40,
809 ],
810 'em' => [
811 'min' => 0,
812 'max' => 3,
813 'step' => 0.1,
814 ],
815 'rem' => [
816 'min' => 0,
817 'max' => 3,
818 'step' => 0.1,
819 ],
820 ],
821 'selectors' => [
822 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-icon-gap: {{SIZE}}{{UNIT}};',
823 ],
824 ]
825 );
826
827 $this->add_responsive_control(
828 'kng_scroll_story_steps_padding',
829 [
830 'label' => esc_html__('Item Padding', 'king-addons'),
831 'type' => Controls_Manager::DIMENSIONS,
832 'size_units' => ['px', '%', 'em', 'rem'],
833 'selectors' => [
834 '{{WRAPPER}} .king-addons-scroll-story__step' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
835 ],
836 ]
837 );
838
839 $this->add_responsive_control(
840 'kng_scroll_story_steps_accent_width',
841 [
842 'label' => esc_html__('Accent Width', 'king-addons'),
843 'type' => Controls_Manager::SLIDER,
844 'size_units' => ['px', 'em', 'rem'],
845 'range' => [
846 'px' => [
847 'min' => 1,
848 'max' => 12,
849 ],
850 'em' => [
851 'min' => 0.05,
852 'max' => 1,
853 'step' => 0.05,
854 ],
855 'rem' => [
856 'min' => 0.05,
857 'max' => 1,
858 'step' => 0.05,
859 ],
860 ],
861 'selectors' => [
862 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-accent-width: {{SIZE}}{{UNIT}};',
863 ],
864 ]
865 );
866
867 $this->add_responsive_control(
868 'kng_scroll_story_steps_accent_offset',
869 [
870 'label' => esc_html__('Accent Offset', 'king-addons'),
871 'type' => Controls_Manager::SLIDER,
872 'size_units' => ['px', 'em', 'rem'],
873 'range' => [
874 'px' => [
875 'min' => 0,
876 'max' => 30,
877 ],
878 'em' => [
879 'min' => 0,
880 'max' => 2,
881 'step' => 0.1,
882 ],
883 'rem' => [
884 'min' => 0,
885 'max' => 2,
886 'step' => 0.1,
887 ],
888 ],
889 'selectors' => [
890 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-accent-offset: {{SIZE}}{{UNIT}};',
891 ],
892 ]
893 );
894
895 $this->add_group_control(
896 Group_Control_Border::get_type(),
897 [
898 'name' => 'kng_scroll_story_steps_border',
899 'selector' => '{{WRAPPER}} .king-addons-scroll-story__step',
900 ]
901 );
902
903 $this->add_group_control(
904 Group_Control_Box_Shadow::get_type(),
905 [
906 'name' => 'kng_scroll_story_steps_shadow',
907 'selector' => '{{WRAPPER}} .king-addons-scroll-story__step',
908 ]
909 );
910
911 $this->add_responsive_control(
912 'kng_scroll_story_steps_radius',
913 [
914 'label' => esc_html__('Item Radius', 'king-addons'),
915 'type' => Controls_Manager::DIMENSIONS,
916 'size_units' => ['px', '%'],
917 'selectors' => [
918 '{{WRAPPER}} .king-addons-scroll-story__step' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
919 ],
920 ]
921 );
922
923 $this->add_responsive_control(
924 'kng_scroll_story_steps_completed_opacity',
925 [
926 'label' => esc_html__('Completed Opacity', 'king-addons'),
927 'type' => Controls_Manager::SLIDER,
928 'size_units' => ['px'],
929 'range' => [
930 'px' => [
931 'min' => 0,
932 'max' => 1,
933 'step' => 0.05,
934 ],
935 ],
936 'selectors' => [
937 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-completed-opacity: {{SIZE}};',
938 ],
939 ]
940 );
941
942 $this->add_control(
943 'kng_scroll_story_steps_background',
944 [
945 'label' => esc_html__('Item Background', 'king-addons'),
946 'type' => Controls_Manager::COLOR,
947 'selectors' => [
948 '{{WRAPPER}} .king-addons-scroll-story__step' => 'background-color: {{VALUE}};',
949 ],
950 ]
951 );
952
953 $this->add_control(
954 'kng_scroll_story_steps_background_hover',
955 [
956 'label' => esc_html__('Item Hover Background', 'king-addons'),
957 'type' => Controls_Manager::COLOR,
958 'selectors' => [
959 '{{WRAPPER}} .king-addons-scroll-story__step:hover' => 'background-color: {{VALUE}};',
960 ],
961 ]
962 );
963
964 $this->add_control(
965 'kng_scroll_story_steps_background_active',
966 [
967 'label' => esc_html__('Active Background', 'king-addons'),
968 'type' => Controls_Manager::COLOR,
969 'selectors' => [
970 '{{WRAPPER}} .king-addons-scroll-story__step.is-active' => 'background-color: {{VALUE}};',
971 ],
972 ]
973 );
974
975 $this->add_control(
976 'kng_scroll_story_steps_border_active',
977 [
978 'label' => esc_html__('Active Border Color', 'king-addons'),
979 'type' => Controls_Manager::COLOR,
980 'selectors' => [
981 '{{WRAPPER}} .king-addons-scroll-story__step.is-active' => 'border-color: {{VALUE}};',
982 ],
983 ]
984 );
985
986 $this->add_control(
987 'kng_scroll_story_steps_accent_color',
988 [
989 'label' => esc_html__('Accent Line', 'king-addons'),
990 'type' => Controls_Manager::COLOR,
991 'selectors' => [
992 '{{WRAPPER}} .king-addons-scroll-story__step-accent' => 'background-color: {{VALUE}};',
993 ],
994 ]
995 );
996
997 $this->add_control(
998 'kng_scroll_story_steps_accent_color_active',
999 [
1000 'label' => esc_html__('Active Accent Line', 'king-addons'),
1001 'type' => Controls_Manager::COLOR,
1002 'selectors' => [
1003 '{{WRAPPER}} .king-addons-scroll-story__step.is-active .king-addons-scroll-story__step-accent' => 'background-color: {{VALUE}};',
1004 ],
1005 ]
1006 );
1007
1008 $this->add_control(
1009 'kng_scroll_story_steps_icon_color',
1010 [
1011 'label' => esc_html__('Icon Color', 'king-addons'),
1012 'type' => Controls_Manager::COLOR,
1013 'selectors' => [
1014 '{{WRAPPER}} .king-addons-scroll-story__step-icon' => 'color: {{VALUE}};',
1015 ],
1016 ]
1017 );
1018
1019 $this->add_control(
1020 'kng_scroll_story_steps_icon_color_active',
1021 [
1022 'label' => esc_html__('Active Icon Color', 'king-addons'),
1023 'type' => Controls_Manager::COLOR,
1024 'selectors' => [
1025 '{{WRAPPER}} .king-addons-scroll-story__step.is-active .king-addons-scroll-story__step-icon' => 'color: {{VALUE}};',
1026 ],
1027 ]
1028 );
1029
1030 $this->add_control(
1031 'kng_scroll_story_steps_title_color',
1032 [
1033 'label' => esc_html__('Title Color', 'king-addons'),
1034 'type' => Controls_Manager::COLOR,
1035 'selectors' => [
1036 '{{WRAPPER}} .king-addons-scroll-story__step-title' => 'color: {{VALUE}};',
1037 ],
1038 ]
1039 );
1040
1041 $this->add_control(
1042 'kng_scroll_story_steps_subtitle_color',
1043 [
1044 'label' => esc_html__('Subtitle Color', 'king-addons'),
1045 'type' => Controls_Manager::COLOR,
1046 'selectors' => [
1047 '{{WRAPPER}} .king-addons-scroll-story__step-subtitle' => 'color: {{VALUE}};',
1048 ],
1049 ]
1050 );
1051
1052 $this->add_group_control(
1053 Group_Control_Typography::get_type(),
1054 [
1055 'name' => 'kng_scroll_story_steps_title_typography',
1056 'selector' => '{{WRAPPER}} .king-addons-scroll-story__step-title',
1057 ]
1058 );
1059
1060 $this->add_group_control(
1061 Group_Control_Typography::get_type(),
1062 [
1063 'name' => 'kng_scroll_story_steps_subtitle_typography',
1064 'selector' => '{{WRAPPER}} .king-addons-scroll-story__step-subtitle',
1065 ]
1066 );
1067
1068 $this->end_controls_section();
1069 }
1070
1071 protected function register_style_content_controls(): void
1072 {
1073 $this->start_controls_section(
1074 'kng_scroll_story_panel_style',
1075 [
1076 'label' => esc_html__('Content Panel', 'king-addons'),
1077 'tab' => Controls_Manager::TAB_STYLE,
1078 ]
1079 );
1080
1081 $this->add_group_control(
1082 Group_Control_Background::get_type(),
1083 [
1084 'name' => 'kng_scroll_story_panel_background',
1085 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel',
1086 ]
1087 );
1088
1089 $this->add_group_control(
1090 Group_Control_Border::get_type(),
1091 [
1092 'name' => 'kng_scroll_story_panel_border',
1093 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel',
1094 ]
1095 );
1096
1097 $this->add_responsive_control(
1098 'kng_scroll_story_panel_radius',
1099 [
1100 'label' => esc_html__('Border Radius', 'king-addons'),
1101 'type' => Controls_Manager::DIMENSIONS,
1102 'size_units' => ['px', '%'],
1103 'selectors' => [
1104 '{{WRAPPER}} .king-addons-scroll-story__panel' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1105 ],
1106 ]
1107 );
1108
1109 $this->add_group_control(
1110 Group_Control_Box_Shadow::get_type(),
1111 [
1112 'name' => 'kng_scroll_story_panel_shadow',
1113 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel',
1114 ]
1115 );
1116
1117 $this->add_responsive_control(
1118 'kng_scroll_story_panel_padding',
1119 [
1120 'label' => esc_html__('Padding', 'king-addons'),
1121 'type' => Controls_Manager::DIMENSIONS,
1122 'size_units' => ['px', '%', 'em', 'rem'],
1123 'selectors' => [
1124 '{{WRAPPER}} .king-addons-scroll-story__panel-inner' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1125 ],
1126 ]
1127 );
1128
1129 $this->add_control(
1130 'kng_scroll_story_panel_title_color',
1131 [
1132 'label' => esc_html__('Title Color', 'king-addons'),
1133 'type' => Controls_Manager::COLOR,
1134 'selectors' => [
1135 '{{WRAPPER}} .king-addons-scroll-story__panel-title' => 'color: {{VALUE}};',
1136 ],
1137 ]
1138 );
1139
1140 $this->add_control(
1141 'kng_scroll_story_panel_subtitle_color',
1142 [
1143 'label' => esc_html__('Subtitle Color', 'king-addons'),
1144 'type' => Controls_Manager::COLOR,
1145 'selectors' => [
1146 '{{WRAPPER}} .king-addons-scroll-story__panel-subtitle' => 'color: {{VALUE}};',
1147 ],
1148 ]
1149 );
1150
1151 $this->add_control(
1152 'kng_scroll_story_panel_description_color',
1153 [
1154 'label' => esc_html__('Description Color', 'king-addons'),
1155 'type' => Controls_Manager::COLOR,
1156 'selectors' => [
1157 '{{WRAPPER}} .king-addons-scroll-story__panel-description' => 'color: {{VALUE}};',
1158 ],
1159 ]
1160 );
1161
1162 $this->add_group_control(
1163 Group_Control_Typography::get_type(),
1164 [
1165 'name' => 'kng_scroll_story_panel_title_typography',
1166 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-title',
1167 ]
1168 );
1169
1170 $this->add_group_control(
1171 Group_Control_Typography::get_type(),
1172 [
1173 'name' => 'kng_scroll_story_panel_subtitle_typography',
1174 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-subtitle',
1175 ]
1176 );
1177
1178 $this->add_group_control(
1179 Group_Control_Typography::get_type(),
1180 [
1181 'name' => 'kng_scroll_story_panel_description_typography',
1182 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-description',
1183 ]
1184 );
1185
1186 $this->add_control(
1187 'kng_scroll_story_panel_cta_heading',
1188 [
1189 'label' => esc_html__('CTA', 'king-addons'),
1190 'type' => Controls_Manager::HEADING,
1191 'separator' => 'before',
1192 ]
1193 );
1194
1195 $this->add_group_control(
1196 Group_Control_Typography::get_type(),
1197 [
1198 'name' => 'kng_scroll_story_panel_cta_typography',
1199 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-cta',
1200 ]
1201 );
1202
1203 $this->add_control(
1204 'kng_scroll_story_panel_cta_color',
1205 [
1206 'label' => esc_html__('CTA Text Color', 'king-addons'),
1207 'type' => Controls_Manager::COLOR,
1208 'selectors' => [
1209 '{{WRAPPER}} .king-addons-scroll-story__panel-cta' => 'color: {{VALUE}};',
1210 ],
1211 ]
1212 );
1213
1214 $this->add_control(
1215 'kng_scroll_story_panel_cta_hover_color',
1216 [
1217 'label' => esc_html__('CTA Hover Text Color', 'king-addons'),
1218 'type' => Controls_Manager::COLOR,
1219 'selectors' => [
1220 '{{WRAPPER}} .king-addons-scroll-story__panel-cta:hover' => 'color: {{VALUE}};',
1221 ],
1222 ]
1223 );
1224
1225 $this->add_control(
1226 'kng_scroll_story_panel_cta_background',
1227 [
1228 'label' => esc_html__('CTA Background', 'king-addons'),
1229 'type' => Controls_Manager::COLOR,
1230 'selectors' => [
1231 '{{WRAPPER}} .king-addons-scroll-story__panel-cta' => 'background-color: {{VALUE}};',
1232 ],
1233 ]
1234 );
1235
1236 $this->add_control(
1237 'kng_scroll_story_panel_cta_hover_background',
1238 [
1239 'label' => esc_html__('CTA Hover Background', 'king-addons'),
1240 'type' => Controls_Manager::COLOR,
1241 'selectors' => [
1242 '{{WRAPPER}} .king-addons-scroll-story__panel-cta:hover' => 'background-color: {{VALUE}};',
1243 ],
1244 ]
1245 );
1246
1247 $this->add_group_control(
1248 Group_Control_Border::get_type(),
1249 [
1250 'name' => 'kng_scroll_story_panel_cta_border',
1251 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-cta',
1252 ]
1253 );
1254
1255 $this->add_control(
1256 'kng_scroll_story_panel_cta_hover_border_color',
1257 [
1258 'label' => esc_html__('CTA Hover Border Color', 'king-addons'),
1259 'type' => Controls_Manager::COLOR,
1260 'selectors' => [
1261 '{{WRAPPER}} .king-addons-scroll-story__panel-cta:hover' => 'border-color: {{VALUE}};',
1262 ],
1263 ]
1264 );
1265
1266 $this->add_responsive_control(
1267 'kng_scroll_story_panel_cta_radius',
1268 [
1269 'label' => esc_html__('CTA Radius', 'king-addons'),
1270 'type' => Controls_Manager::DIMENSIONS,
1271 'size_units' => ['px', '%'],
1272 'selectors' => [
1273 '{{WRAPPER}} .king-addons-scroll-story__panel-cta' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1274 ],
1275 ]
1276 );
1277
1278 $this->add_responsive_control(
1279 'kng_scroll_story_panel_cta_padding',
1280 [
1281 'label' => esc_html__('CTA Padding', 'king-addons'),
1282 'type' => Controls_Manager::DIMENSIONS,
1283 'size_units' => ['px', '%', 'em', 'rem'],
1284 'selectors' => [
1285 '{{WRAPPER}} .king-addons-scroll-story__panel-cta' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1286 ],
1287 ]
1288 );
1289
1290 $this->end_controls_section();
1291 }
1292
1293 protected function register_style_media_controls(): void
1294 {
1295 $this->start_controls_section(
1296 'kng_scroll_story_media_style',
1297 [
1298 'label' => esc_html__('Media', 'king-addons'),
1299 'tab' => Controls_Manager::TAB_STYLE,
1300 ]
1301 );
1302
1303 $this->add_responsive_control(
1304 'kng_scroll_story_media_padding',
1305 [
1306 'label' => esc_html__('Media Padding', 'king-addons'),
1307 'type' => Controls_Manager::DIMENSIONS,
1308 'size_units' => ['px', '%', 'em', 'rem'],
1309 'selectors' => [
1310 '{{WRAPPER}} .king-addons-scroll-story__panel-media' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1311 ],
1312 ]
1313 );
1314
1315 $this->add_control(
1316 'kng_scroll_story_media_ratio',
1317 [
1318 'label' => esc_html__('Aspect Ratio', 'king-addons'),
1319 'type' => Controls_Manager::SELECT,
1320 'default' => 'auto',
1321 'options' => [
1322 'auto' => esc_html__('Auto', 'king-addons'),
1323 '1-1' => esc_html__('1:1', 'king-addons'),
1324 '4-3' => esc_html__('4:3', 'king-addons'),
1325 '3-4' => esc_html__('3:4', 'king-addons'),
1326 '16-9' => esc_html__('16:9', 'king-addons'),
1327 '21-9' => esc_html__('21:9', 'king-addons'),
1328 'custom' => esc_html__('Custom', 'king-addons'),
1329 ],
1330 'render_type' => 'template',
1331 ]
1332 );
1333
1334 $this->add_control(
1335 'kng_scroll_story_media_ratio_custom',
1336 [
1337 'label' => esc_html__('Custom Ratio', 'king-addons'),
1338 'type' => Controls_Manager::TEXT,
1339 'placeholder' => esc_html__('16/9', 'king-addons'),
1340 'description' => esc_html__('Use format like 16/9 or 4:3.', 'king-addons'),
1341 'condition' => [
1342 'kng_scroll_story_media_ratio' => 'custom',
1343 ],
1344 'render_type' => 'template',
1345 ]
1346 );
1347
1348 $this->add_control(
1349 'kng_scroll_story_media_fit',
1350 [
1351 'label' => esc_html__('Object Fit', 'king-addons'),
1352 'type' => Controls_Manager::SELECT,
1353 'default' => 'cover',
1354 'options' => [
1355 'cover' => esc_html__('Cover', 'king-addons'),
1356 'contain' => esc_html__('Contain', 'king-addons'),
1357 'fill' => esc_html__('Fill', 'king-addons'),
1358 'scale-down' => esc_html__('Scale Down', 'king-addons'),
1359 ],
1360 'selectors' => [
1361 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-media-fit: {{VALUE}};',
1362 ],
1363 ]
1364 );
1365
1366 $this->add_responsive_control(
1367 'kng_scroll_story_media_max_height',
1368 [
1369 'label' => esc_html__('Max Height', 'king-addons'),
1370 'type' => Controls_Manager::SLIDER,
1371 'size_units' => ['px', 'vh'],
1372 'range' => [
1373 'px' => [
1374 'min' => 100,
1375 'max' => 1200,
1376 'step' => 10,
1377 ],
1378 'vh' => [
1379 'min' => 10,
1380 'max' => 100,
1381 ],
1382 ],
1383 'selectors' => [
1384 '{{WRAPPER}} .king-addons-scroll-story' => '--kng-scroll-story-media-max-height: {{SIZE}}{{UNIT}};',
1385 ],
1386 ]
1387 );
1388
1389 $this->add_responsive_control(
1390 'kng_scroll_story_media_radius',
1391 [
1392 'label' => esc_html__('Media Radius', 'king-addons'),
1393 'type' => Controls_Manager::SLIDER,
1394 'size_units' => ['px', '%'],
1395 'selectors' => [
1396 '{{WRAPPER}} .king-addons-scroll-story__panel-media img, {{WRAPPER}} .king-addons-scroll-story__panel-media video' => 'border-radius: {{SIZE}}{{UNIT}};',
1397 ],
1398 ]
1399 );
1400
1401 $this->add_group_control(
1402 Group_Control_Box_Shadow::get_type(),
1403 [
1404 'name' => 'kng_scroll_story_media_shadow',
1405 'selector' => '{{WRAPPER}} .king-addons-scroll-story__panel-media img, {{WRAPPER}} .king-addons-scroll-story__panel-media video',
1406 ]
1407 );
1408
1409 $this->end_controls_section();
1410 }
1411
1412 public function render(): void
1413 {
1414 $settings = $this->get_settings_for_display();
1415 $steps = $settings['kng_scroll_story_steps'] ?? [];
1416
1417 if (empty($steps)) {
1418 return;
1419 }
1420
1421 $offset = (int) ($settings['kng_scroll_story_activation_offset']['size'] ?? 40);
1422 $offset = max(10, min(80, $offset));
1423
1424 $options = [
1425 'activationOffset' => $offset,
1426 'smoothScroll' => (($settings['kng_scroll_story_smooth_scroll'] ?? 'yes') === 'yes'),
1427 'scrollDuration' => (int) ($settings['kng_scroll_story_scroll_duration'] ?? 600),
1428 ];
1429
1430 $ratio_map = [
1431 '1-1' => '1 / 1',
1432 '4-3' => '4 / 3',
1433 '3-4' => '3 / 4',
1434 '16-9' => '16 / 9',
1435 '21-9' => '21 / 9',
1436 ];
1437 $ratio_setting = $settings['kng_scroll_story_media_ratio'] ?? 'auto';
1438 $ratio_value = '';
1439 if ('custom' === $ratio_setting) {
1440 $ratio_value = $this->sanitize_ratio($settings['kng_scroll_story_media_ratio_custom'] ?? '');
1441 } elseif (isset($ratio_map[$ratio_setting])) {
1442 $ratio_value = $ratio_map[$ratio_setting];
1443 }
1444
1445 $this->add_render_attribute(
1446 'wrapper',
1447 [
1448 'class' => 'king-addons-scroll-story',
1449 'data-settings' => wp_json_encode($options),
1450 ]
1451 );
1452
1453 if (!empty($ratio_value)) {
1454 $this->add_render_attribute('wrapper', 'style', '--kng-scroll-story-media-ratio: ' . esc_attr($ratio_value) . ';');
1455 }
1456
1457 $widget_id = $this->get_id();
1458
1459 echo '<div ' . $this->get_render_attribute_string('wrapper') . '>';
1460 echo '<div class="king-addons-scroll-story__inner">';
1461 echo '<div class="king-addons-scroll-story__grid">';
1462
1463 echo '<div class="king-addons-scroll-story__steps" role="list">';
1464 foreach ($steps as $index => $step) {
1465 $title = $step['step_title'] ?? '';
1466 $subtitle = $step['step_subtitle'] ?? '';
1467 $icon = $step['step_icon'] ?? [];
1468 $step_id = 'kng-scroll-story-step-' . $widget_id . '-' . $index;
1469 $panel_id = 'kng-scroll-story-panel-' . $widget_id . '-' . $index;
1470
1471 $classes = ['king-addons-scroll-story__step'];
1472 if (0 === $index) {
1473 $classes[] = 'is-active';
1474 } else {
1475 $classes[] = 'is-upcoming';
1476 }
1477
1478 echo '<div class="' . esc_attr(implode(' ', $classes)) . '" data-step-index="' . esc_attr((string) $index) . '" role="listitem">';
1479 echo '<span class="king-addons-scroll-story__step-accent" aria-hidden="true"></span>';
1480 echo '<button id="' . esc_attr($step_id) . '" class="king-addons-scroll-story__step-button" type="button" aria-controls="' . esc_attr($panel_id) . '"' . (0 === $index ? ' aria-current="step"' : '') . '>';
1481
1482 if (!empty($icon['value'])) {
1483 echo '<span class="king-addons-scroll-story__step-icon" aria-hidden="true">';
1484 Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']);
1485 echo '</span>';
1486 }
1487
1488 echo '<span class="king-addons-scroll-story__step-text">';
1489 if (!empty($title)) {
1490 echo '<span class="king-addons-scroll-story__step-title">' . esc_html($title) . '</span>';
1491 }
1492 if (!empty($subtitle)) {
1493 echo '<span class="king-addons-scroll-story__step-subtitle">' . esc_html($subtitle) . '</span>';
1494 }
1495 echo '</span>';
1496
1497 echo '</button>';
1498 echo '</div>';
1499 }
1500 echo '</div>';
1501
1502 echo '<div class="king-addons-scroll-story__content">';
1503 foreach ($steps as $index => $step) {
1504 $title = $step['step_title'] ?? '';
1505 $subtitle = $step['step_subtitle'] ?? '';
1506 $description = $step['step_description'] ?? '';
1507 $media_type = $step['step_media_type'] ?? 'none';
1508 $media_image = $step['step_media_image'] ?? [];
1509 $cta_text = $step['step_cta_text'] ?? '';
1510 $cta_link = $step['step_cta_link'] ?? [];
1511 $step_id = 'kng-scroll-story-step-' . $widget_id . '-' . $index;
1512 $panel_id = 'kng-scroll-story-panel-' . $widget_id . '-' . $index;
1513
1514 $panel_classes = ['king-addons-scroll-story__panel'];
1515 if (0 === $index) {
1516 $panel_classes[] = 'is-active';
1517 $panel_classes[] = 'is-animated';
1518 }
1519
1520 $panel_hidden = 0 === $index ? '' : ' hidden';
1521 echo '<div id="' . esc_attr($panel_id) . '" class="' . esc_attr(implode(' ', $panel_classes)) . '" data-step-index="' . esc_attr((string) $index) . '" role="region" aria-labelledby="' . esc_attr($step_id) . '" aria-hidden="' . (0 === $index ? 'false' : 'true') . '"' . $panel_hidden . '>';
1522 echo '<div class="king-addons-scroll-story__panel-inner">';
1523
1524 if (!empty($title)) {
1525 echo '<div class="king-addons-scroll-story__panel-title">' . esc_html($title) . '</div>';
1526 }
1527 if (!empty($subtitle)) {
1528 echo '<div class="king-addons-scroll-story__panel-subtitle">' . esc_html($subtitle) . '</div>';
1529 }
1530 if (!empty($description)) {
1531 echo '<div class="king-addons-scroll-story__panel-description">' . wp_kses_post($description) . '</div>';
1532 }
1533
1534 if (!empty($cta_text) && !empty($cta_link['url'])) {
1535 $cta_attrs = $this->get_link_attributes($cta_link);
1536 echo '<a class="king-addons-scroll-story__panel-cta" href="' . esc_url($cta_link['url']) . '"' . $cta_attrs . '>' . esc_html($cta_text) . '</a>';
1537 }
1538
1539 echo '</div>';
1540
1541 if ('image' === $media_type && (!empty($media_image['id']) || !empty($media_image['url']))) {
1542 echo '<div class="king-addons-scroll-story__panel-media">';
1543 if (!empty($media_image['id'])) {
1544 echo Group_Control_Image_Size::get_attachment_image_html($step, 'step_media_image_size', 'step_media_image'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1545 } else {
1546 $alt = $media_image['alt'] ?? '';
1547 echo '<img src="' . esc_url($media_image['url']) . '" alt="' . esc_attr($alt) . '" loading="lazy">';
1548 }
1549 echo '</div>';
1550 }
1551
1552 echo '</div>';
1553 }
1554 echo '</div>';
1555
1556 echo '</div>';
1557 echo '</div>';
1558 echo '</div>';
1559 }
1560
1561 public function register_pro_notice_controls(): void
1562 {
1563 if (!king_addons_can_use_pro()) {
1564 Core::renderProFeaturesSection($this, '', Controls_Manager::RAW_HTML, 'scroll-story-sections', [
1565 'Sticky media panel with offsets',
1566 'Progress line, dots, and step counters',
1567 'Lottie per step with playback control',
1568 'Elementor templates for content and media',
1569 'Deep linking and anchor sync',
1570 ]);
1571 }
1572 }
1573
1574 protected function get_default_steps(): array
1575 {
1576 return [
1577 [
1578 'step_title' => esc_html__('Discover the story', 'king-addons'),
1579 'step_subtitle' => esc_html__('Step One', 'king-addons'),
1580 'step_description' => esc_html__('Introduce the core idea with a short, clear description that sets the stage.', 'king-addons'),
1581 'step_media_type' => 'image',
1582 ],
1583 [
1584 'step_title' => esc_html__('Highlight the shift', 'king-addons'),
1585 'step_subtitle' => esc_html__('Step Two', 'king-addons'),
1586 'step_description' => esc_html__('Explain the transformation and the impact you want visitors to remember.', 'king-addons'),
1587 'step_media_type' => 'image',
1588 ],
1589 [
1590 'step_title' => esc_html__('Drive to action', 'king-addons'),
1591 'step_subtitle' => esc_html__('Step Three', 'king-addons'),
1592 'step_description' => esc_html__('Close with a decisive benefit and guide readers to the next step.', 'king-addons'),
1593 'step_media_type' => 'image',
1594 ],
1595 ];
1596 }
1597
1598 protected function is_pro_enabled(): bool
1599 {
1600 return function_exists('king_addons_freemius') && king_addons_freemius()->can_use_premium_code__premium_only();
1601 }
1602
1603 protected function get_pro_control_class(string $extra = ''): string
1604 {
1605 if ($this->is_pro_enabled()) {
1606 return $extra;
1607 }
1608
1609 return trim('king-addons-pro-control ' . $extra);
1610 }
1611
1612 protected function get_link_attributes(array $link): string
1613 {
1614 $attrs = '';
1615 $rels = [];
1616
1617 if (!empty($link['is_external'])) {
1618 $attrs .= ' target="_blank"';
1619 $rels[] = 'noopener';
1620 $rels[] = 'noreferrer';
1621 }
1622
1623 if (!empty($link['nofollow'])) {
1624 $rels[] = 'nofollow';
1625 }
1626
1627 if (!empty($rels)) {
1628 $attrs .= ' rel="' . esc_attr(implode(' ', array_unique($rels))) . '"';
1629 }
1630
1631 return $attrs;
1632 }
1633
1634 protected function sanitize_ratio(string $ratio): string
1635 {
1636 $ratio = trim($ratio);
1637 if ($ratio === '') {
1638 return '';
1639 }
1640
1641 if (preg_match('/^(\d+(?:\.\d+)?)\s*[:\/]\s*(\d+(?:\.\d+)?)$/', $ratio, $matches)) {
1642 $width = (float) $matches[1];
1643 $height = (float) $matches[2];
1644 if ($width > 0 && $height > 0) {
1645 return $width . ' / ' . $height;
1646 }
1647 }
1648
1649 return '';
1650 }
1651 }
1652