PluginProbe
Elementor Website Builder – more than just a page builder / 3.8.0-beta1
Elementor Website Builder – more than just a page builder v3.8.0-beta1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / elements / container.php

container.php in Elementor Website Builder – more than just a page builder 3.8.0-beta1, at includes/elements/container.php

1,637 lines 38.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Includes\Elements;
3
4 use Elementor\Controls_Manager;
5 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
6 use Elementor\Element_Base;
7 use Elementor\Embed;
8 use Elementor\Group_Control_Background;
9 use Elementor\Group_Control_Border;
10 use Elementor\Group_Control_Box_Shadow;
11 use Elementor\Group_Control_Css_Filter;
12 use Elementor\Group_Control_Flex_Container;
13 use Elementor\Group_Control_Flex_Item;
14 use Elementor\Plugin;
15 use Elementor\Shapes;
16 use Elementor\Utils;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 class Container extends Element_Base {
23
24 /**
25 * @var \Elementor\Core\Kits\Documents\Kit
26 */
27 private $active_kit;
28
29 /**
30 * Container constructor.
31 *
32 * @param array $data
33 * @param array|null $args
34 *
35 * @return void
36 */
37 public function __construct( array $data = [], array $args = null ) {
38 parent::__construct( $data, $args );
39
40 $this->active_kit = Plugin::$instance->kits_manager->get_active_kit();
41 }
42
43 /**
44 * Get the element type.
45 *
46 * @return string
47 */
48 public static function get_type() {
49 return 'container';
50 }
51
52 /**
53 * Get the element name.
54 *
55 * @return string
56 */
57 public function get_name() {
58 return 'container';
59 }
60
61 /**
62 * Get the element display name.
63 *
64 * @return string
65 */
66 public function get_title() {
67 return esc_html__( 'Container', 'elementor' );
68 }
69
70 /**
71 * Get the element display icon.
72 *
73 * @return string
74 */
75 public function get_icon() {
76 return 'eicon-container';
77 }
78
79 /**
80 * Override the render attributes to add a custom wrapper class.
81 *
82 * @return void
83 */
84 protected function add_render_attributes() {
85 parent::add_render_attributes();
86
87 $this->add_render_attribute( '_wrapper', [
88 'class' => [
89 'e-container',
90 ],
91 ] );
92 }
93
94 /**
95 * Override the initial element config to display the Container in the panel.
96 *
97 * @return array
98 */
99 protected function get_initial_config() {
100 $config = parent::get_initial_config();
101
102 $config['controls'] = $this->get_controls();
103 $config['tabs_controls'] = $this->get_tabs_controls();
104 $config['show_in_panel'] = true;
105 $config['categories'] = [ 'layout' ];
106
107 return $config;
108 }
109
110 /**
111 * Render the element JS template.
112 *
113 * @return void
114 */
115 protected function content_template() {
116 ?>
117 <# if ( 'boxed' === settings.content_width ) { #>
118 <div class="e-container__inner">
119 <#
120 }
121 if ( settings.background_video_link ) {
122 let videoAttributes = 'autoplay muted playsinline';
123
124 if ( ! settings.background_play_once ) {
125 videoAttributes += ' loop';
126 }
127
128 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
129
130 if ( ! settings.background_play_on_mobile ) {
131 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
132 }
133 #>
134 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
135 <div class="elementor-background-video-embed"></div>
136 <video class="elementor-background-video-hosted elementor-html5-video" {{ videoAttributes }}></video>
137 </div>
138 <# } #>
139 <div class="elementor-shape elementor-shape-top"></div>
140 <div class="elementor-shape elementor-shape-bottom"></div>
141 <# if ( 'boxed' === settings.content_width ) { #>
142 </div>
143 <# } #>
144 <?php
145 }
146
147 /**
148 * Render the video background markup.
149 *
150 * @return void
151 */
152 private function render_video_background() {
153 $settings = $this->get_settings_for_display();
154
155 if ( 'video' !== $settings['background_background'] ) {
156 return;
157 }
158
159 if ( ! $settings['background_video_link'] ) {
160 return;
161 }
162
163 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
164
165 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-background-video-container' );
166
167 if ( ! $settings['background_play_on_mobile'] ) {
168 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-phone' );
169 }
170
171 ?><div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
172 <?php if ( $video_properties ) : ?>
173 <div class="elementor-background-video-embed"></div>
174 <?php
175 else :
176 $video_tag_attributes = 'autoplay muted playsinline';
177
178 if ( 'yes' !== $settings['background_play_once'] ) {
179 $video_tag_attributes .= ' loop';
180 }
181 ?>
182 <video class="elementor-background-video-hosted elementor-html5-video" <?php echo esc_attr( $video_tag_attributes ); ?>></video>
183 <?php endif; ?>
184 </div><?php
185 }
186
187 /**
188 * Render the Container's shape divider.
189 * TODO: Copied from `section.php`.
190 *
191 * Used to generate the shape dividers HTML.
192 *
193 * @param string $side - Shape divider side, used to set the shape key.
194 *
195 * @return void
196 */
197 private function render_shape_divider( $side ) {
198 $settings = $this->get_active_settings();
199 $base_setting_key = "shape_divider_$side";
200 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
201 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
202
203 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
204 return;
205 }
206 ?>
207 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php
208 Utils::print_unescaped_internal_string( $negative ? 'true' : 'false' );
209 ?>">
210 <?php
211 // PHPCS - The file content is being read from a strict file path structure.
212 echo Utils::file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
213 ?>
214 </div>
215 <?php
216 }
217
218 /**
219 * Print safe HTML tag for the element based on the element settings.
220 *
221 * @return void
222 */
223 private function print_html_tag() {
224 $html_tag = $this->get_settings( 'html_tag' );
225
226 if ( empty( $html_tag ) ) {
227 $html_tag = 'div';
228 }
229
230 Utils::print_validated_html_tag( $html_tag );
231 }
232
233 /**
234 * Before rendering the container content. (Print the opening tag, etc.)
235 *
236 * @return void
237 */
238 public function before_render() {
239 $settings = $this->get_settings_for_display();
240 $link = $settings['link'];
241
242 if ( ! empty( $link['url'] ) ) {
243 $this->add_link_attributes( '_wrapper', $link );
244 }
245
246 ?><<?php $this->print_html_tag(); ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
247 <?php
248 if ( $this->is_boxed_container( $settings ) ) { ?>
249 <div class="e-container__inner">
250 <?php }
251
252 $this->render_video_background();
253
254 if ( ! empty( $settings['shape_divider_top'] ) ) {
255 $this->render_shape_divider( 'top' );
256 }
257
258 if ( ! empty( $settings['shape_divider_bottom'] ) ) {
259 $this->render_shape_divider( 'bottom' );
260 }
261 }
262
263 /**
264 * After rendering the Container content. (Print the closing tag, etc.)
265 *
266 * @return void
267 */
268 public function after_render() {
269 $settings = $this->get_settings_for_display();
270 if ( $this->is_boxed_container( $settings ) ) { ?>
271 </div>
272 <?php } ?>
273 </<?php $this->print_html_tag(); ?>>
274 <?php
275 }
276
277 private function is_boxed_container( array $settings ) {
278 return ! empty( $settings['content_width'] ) && 'boxed' === $settings['content_width'];
279 }
280
281 /**
282 * Override the default child type to allow widgets & containers as children.
283 *
284 * @param array $element_data
285 *
286 * @return \Elementor\Element_Base|\Elementor\Widget_Base|null
287 */
288 protected function _get_default_child_type( array $element_data ) {
289 if ( 'container' === $element_data['elType'] ) {
290 return Plugin::$instance->elements_manager->get_element_types( 'container' );
291 }
292
293 return Plugin::$instance->widgets_manager->get_widget_types( $element_data['widgetType'] );
294 }
295
296 /**
297 * Register the Container's layout controls.
298 *
299 * @return void
300 */
301 protected function register_container_layout_controls() {
302 $this->start_controls_section(
303 'section_layout_container',
304 [
305 'label' => esc_html__( 'Container', 'elementor' ),
306 'tab' => Controls_Manager::TAB_LAYOUT,
307 ]
308 );
309
310 $active_breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
311
312 if ( array_key_exists( Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA, $active_breakpoints ) ) {
313 $min_affected_device = Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA;
314 } else {
315 $min_affected_device = Breakpoints_Manager::BREAKPOINT_KEY_TABLET;
316 }
317
318 $this->add_control(
319 'content_width',
320 [
321 'label' => esc_html__( 'Content Width', 'elementor' ),
322 'type' => Controls_Manager::SELECT,
323 'default' => 'boxed',
324 'options' => [
325 'boxed' => esc_html__( 'Boxed', 'elementor' ),
326 'full' => esc_html__( 'Full Width', 'elementor' ),
327 ],
328 'render_type' => 'template',
329 'prefix_class' => 'e-container--width-',
330 'frontend_available' => true,
331 ]
332 );
333
334 $width_control_settings = [
335 'label' => esc_html__( 'Width', 'elementor' ),
336 'type' => Controls_Manager::SLIDER,
337 'size_units' => [ 'px', '%', 'vw' ],
338 'range' => [
339 'px' => [
340 'min' => 500,
341 'max' => 1600,
342 ],
343 '%' => [
344 'min' => 0,
345 'max' => 100,
346 ],
347 'vw' => [
348 'min' => 0,
349 'max' => 100,
350 ],
351 ],
352 'default' => [
353 'unit' => '%',
354 ],
355 'min_affected_device' => [
356 Breakpoints_Manager::BREAKPOINT_KEY_DESKTOP => $min_affected_device,
357 Breakpoints_Manager::BREAKPOINT_KEY_LAPTOP => $min_affected_device,
358 Breakpoints_Manager::BREAKPOINT_KEY_TABLET_EXTRA => $min_affected_device,
359 Breakpoints_Manager::BREAKPOINT_KEY_TABLET => $min_affected_device,
360 Breakpoints_Manager::BREAKPOINT_KEY_MOBILE_EXTRA => $min_affected_device,
361 ],
362 'separator' => 'none',
363 ];
364
365 $this->add_responsive_control(
366 'width',
367 array_merge( $width_control_settings, [
368 'selectors' => [
369 '{{WRAPPER}}' => '--width: {{SIZE}}{{UNIT}};',
370 ],
371 'condition' => [
372 'content_width' => 'full',
373 ],
374 'device_args' => [
375 Breakpoints_Manager::BREAKPOINT_KEY_DESKTOP => [
376 'placeholder' => [
377 'size' => 100,
378 'unit' => '%',
379 ],
380 ],
381 Breakpoints_Manager::BREAKPOINT_KEY_MOBILE => [
382 // The mobile width is not inherited from the higher breakpoint width controls.
383 'placeholder' => [
384 'size' => 100,
385 'unit' => '%',
386 ],
387 ],
388 ],
389 ] )
390 );
391
392 $this->add_responsive_control(
393 'boxed_width',
394 array_merge( $width_control_settings, [
395 'selectors' => [
396 '{{WRAPPER}}' => '--content-width: {{SIZE}}{{UNIT}};',
397 ],
398 'condition' => [
399 'content_width' => 'boxed',
400 ],
401 'default' => [
402 'unit' => 'px',
403 ],
404 'device_args' => [
405 Breakpoints_Manager::BREAKPOINT_KEY_DESKTOP => [
406 // Use the default width from the kit as a placeholder.
407 'placeholder' => $this->active_kit->get_settings_for_display( 'container_width' ),
408 ],
409 Breakpoints_Manager::BREAKPOINT_KEY_MOBILE => [
410 // The mobile width is not inherited from the higher breakpoint width controls.
411 'placeholder' => [
412 'size' => 100,
413 'unit' => '%',
414 ],
415 ],
416 ],
417 ] )
418 );
419
420 $this->add_responsive_control(
421 'min_height',
422 [
423 'label' => esc_html__( 'Min Height', 'elementor' ),
424 'type' => Controls_Manager::SLIDER,
425 'size_units' => [ 'px', 'vh' ],
426 'range' => [
427 'px' => [
428 'min' => 0,
429 'max' => 1440,
430 ],
431 'vh' => [
432 'min' => 0,
433 'max' => 100,
434 ],
435 ],
436 'description' => sprintf(
437 esc_html__( 'To achieve full height Container use %s.', 'elementor' ),
438 '100vh'
439 ),
440 'selectors' => [
441 '{{WRAPPER}}' => '--min-height: {{SIZE}}{{UNIT}};',
442 ],
443 ]
444 );
445
446 $this->add_group_control(
447 Group_Control_Flex_Container::get_type(),
448 [
449 'name' => 'flex',
450 'selector' => '{{WRAPPER}}',
451 'fields_options' => [
452 'gap' => [
453 'label' => esc_html_x( 'Gap between elements', 'Flex Container Control', 'elementor' ),
454 'device_args' => [
455 Breakpoints_Manager::BREAKPOINT_KEY_DESKTOP => [
456 // Use the default gap from the kit as a placeholder.
457 'placeholder' => $this->active_kit->get_settings_for_display( 'space_between_widgets' ),
458 ],
459 ],
460 ],
461 ],
462 ]
463 );
464
465 $this->end_controls_section();
466 }
467
468 /**
469 * Register the Container's items layout controls.
470 *
471 * @return void
472 */
473 protected function register_items_layout_controls() {
474 $this->start_controls_section(
475 'section_layout_additional_options',
476 [
477 'label' => esc_html__( 'Additional Options', 'elementor' ),
478 'tab' => Controls_Manager::TAB_LAYOUT,
479 ]
480 );
481
482 $this->add_control(
483 'overflow',
484 [
485 'label' => esc_html__( 'Overflow', 'elementor' ),
486 'type' => Controls_Manager::SELECT,
487 'default' => '',
488 'options' => [
489 '' => esc_html__( 'Default', 'elementor' ),
490 'hidden' => esc_html__( 'Hidden', 'elementor' ),
491 'auto' => esc_html__( 'Auto', 'elementor' ),
492 ],
493 'selectors' => [
494 '{{WRAPPER}}' => '--overflow: {{VALUE}}',
495 ],
496 ]
497 );
498
499 $possible_tags = [
500 'div' => 'div',
501 'header' => 'header',
502 'footer' => 'footer',
503 'main' => 'main',
504 'article' => 'article',
505 'section' => 'section',
506 'aside' => 'aside',
507 'nav' => 'nav',
508 'a' => 'a ' . esc_html__( '(link)', 'elementor' ),
509 ];
510
511 $options = [
512 '' => esc_html__( 'Default', 'elementor' ),
513 ] + $possible_tags;
514
515 $this->add_control(
516 'html_tag',
517 [
518 'label' => esc_html__( 'HTML Tag', 'elementor' ),
519 'type' => Controls_Manager::SELECT,
520 'options' => $options,
521 ]
522 );
523
524 $this->add_control(
525 'link_note',
526 [
527 'type' => Controls_Manager::RAW_HTML,
528 'content_classes' => 'elementor-panel-alert elementor-panel-alert-warning',
529 'raw' => esc_html__( 'Don’t add links to elements nested in this container - it will break the layout.', 'elementor' ),
530 'condition' => [
531 'html_tag' => 'a',
532 ],
533 ]
534 );
535
536 $this->add_control(
537 'link',
538 [
539 'label' => esc_html__( 'Link', 'elementor' ),
540 'type' => Controls_Manager::URL,
541 'dynamic' => [
542 'active' => true,
543 ],
544 'placeholder' => esc_html__( 'https://your-link.com', 'elementor' ),
545 'condition' => [
546 'html_tag' => 'a',
547 ],
548 ]
549 );
550
551 $this->end_controls_section();
552 }
553
554 /**
555 * Register the Container's layout tab.
556 *
557 * @return void
558 */
559 protected function register_layout_tab() {
560 $this->register_container_layout_controls();
561
562 $this->register_items_layout_controls();
563 }
564
565 /**
566 * Register the Container's background controls.
567 *
568 * @return void
569 */
570 protected function register_background_controls() {
571 $this->start_controls_section(
572 'section_background',
573 [
574 'label' => esc_html__( 'Background', 'elementor' ),
575 'tab' => Controls_Manager::TAB_STYLE,
576 ]
577 );
578
579 $this->start_controls_tabs( 'tabs_background' );
580
581 /**
582 * Normal.
583 */
584 $this->start_controls_tab(
585 'tab_background_normal',
586 [
587 'label' => esc_html__( 'Normal', 'elementor' ),
588 ]
589 );
590
591 $this->add_group_control(
592 Group_Control_Background::get_type(),
593 [
594 'name' => 'background',
595 'types' => [ 'classic', 'gradient', 'video', 'slideshow' ],
596 'fields_options' => [
597 'background' => [
598 'frontend_available' => true,
599 ],
600 ],
601 ]
602 );
603
604 $this->end_controls_tab();
605
606 /**
607 * Hover.
608 */
609 $this->start_controls_tab(
610 'tab_background_hover',
611 [
612 'label' => esc_html__( 'Hover', 'elementor' ),
613 ]
614 );
615
616 $this->add_group_control(
617 Group_Control_Background::get_type(),
618 [
619 'name' => 'background_hover',
620 'selector' => '{{WRAPPER}}:hover',
621 ]
622 );
623
624 $this->add_control(
625 'background_hover_transition',
626 [
627 'label' => esc_html__( 'Transition Duration', 'elementor' ),
628 'type' => Controls_Manager::SLIDER,
629 'default' => [
630 'size' => 0.3,
631 ],
632 'range' => [
633 'px' => [
634 'max' => 3,
635 'step' => 0.1,
636 ],
637 ],
638 'render_type' => 'ui',
639 'separator' => 'before',
640 ]
641 );
642
643 $this->end_controls_tab();
644
645 $this->end_controls_tabs();
646
647 $this->end_controls_section();
648 }
649
650 /**
651 * Register the Container's background overlay controls.
652 *
653 * @return void
654 */
655 protected function register_background_overlay_controls() {
656 $this->start_controls_section(
657 'section_background_overlay',
658 [
659 'label' => esc_html__( 'Background Overlay', 'elementor' ),
660 'tab' => Controls_Manager::TAB_STYLE,
661 ]
662 );
663
664 $this->start_controls_tabs( 'tabs_background_overlay' );
665
666 /**
667 * Normal.
668 */
669 $this->start_controls_tab(
670 'tab_background_overlay',
671 [
672 'label' => esc_html__( 'Normal', 'elementor' ),
673 ]
674 );
675
676 $this->add_group_control(
677 Group_Control_Background::get_type(),
678 [
679 'name' => 'background_overlay',
680 'selector' => '{{WRAPPER}}::before',
681 'fields_options' => [
682 'background' => [
683 'selectors' => [
684 // Hack to set the `::before` content in order to render it only when there is a background overlay.
685 '{{WRAPPER}}::before' => '--background-overlay: \'\';',
686 ],
687 ],
688 ],
689 ]
690 );
691
692 $this->add_control(
693 'background_overlay_opacity',
694 [
695 'label' => esc_html__( 'Opacity', 'elementor' ),
696 'type' => Controls_Manager::SLIDER,
697 'default' => [
698 'size' => .5,
699 ],
700 'range' => [
701 'px' => [
702 'max' => 1,
703 'step' => 0.01,
704 ],
705 ],
706 'selectors' => [
707 '{{WRAPPER}}' => '--overlay-opacity: {{SIZE}};',
708 ],
709 'condition' => [
710 'background_overlay_background' => [ 'classic', 'gradient' ],
711 ],
712 ]
713 );
714
715 $this->add_group_control(
716 Group_Control_Css_Filter::get_type(),
717 [
718 'name' => 'css_filters',
719 'selector' => '{{WRAPPER}}::before',
720 'conditions' => [
721 'relation' => 'or',
722 'terms' => [
723 [
724 'name' => 'background_overlay_image[url]',
725 'operator' => '!==',
726 'value' => '',
727 ],
728 [
729 'name' => 'background_overlay_color',
730 'operator' => '!==',
731 'value' => '',
732 ],
733 ],
734 ],
735 ]
736 );
737
738 $this->add_control(
739 'overlay_blend_mode',
740 [
741 'label' => esc_html__( 'Blend Mode', 'elementor' ),
742 'type' => Controls_Manager::SELECT,
743 'options' => [
744 '' => esc_html__( 'Normal', 'elementor' ),
745 'multiply' => esc_html__( 'Multiply', 'elementor' ),
746 'screen' => esc_html__( 'Screen', 'elementor' ),
747 'overlay' => esc_html__( 'Overlay', 'elementor' ),
748 'darken' => esc_html__( 'Darken', 'elementor' ),
749 'lighten' => esc_html__( 'Lighten', 'elementor' ),
750 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
751 'saturation' => esc_html__( 'Saturation', 'elementor' ),
752 'color' => esc_html__( 'Color', 'elementor' ),
753 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
754 ],
755 'selectors' => [
756 '{{WRAPPER}}' => '--overlay-mix-blend-mode: {{VALUE}}',
757 ],
758 'conditions' => [
759 'relation' => 'or',
760 'terms' => [
761 [
762 'name' => 'background_overlay_image[url]',
763 'operator' => '!==',
764 'value' => '',
765 ],
766 [
767 'name' => 'background_overlay_color',
768 'operator' => '!==',
769 'value' => '',
770 ],
771 ],
772 ],
773 ]
774 );
775
776 $this->end_controls_tab();
777
778 /**
779 * Hover.
780 */
781 $this->start_controls_tab(
782 'tab_background_overlay_hover',
783 [
784 'label' => esc_html__( 'Hover', 'elementor' ),
785 ]
786 );
787
788 $this->add_group_control(
789 Group_Control_Background::get_type(),
790 [
791 'name' => 'background_overlay_hover',
792 'selector' => '{{WRAPPER}}:hover::before',
793 'fields_options' => [
794 'background' => [
795 'selectors' => [
796 // Hack to set the `::before` content in order to render it only when there is a background overlay.
797 '{{WRAPPER}}:hover::before' => '--background-overlay: \'\';',
798 ],
799 ],
800 ],
801 ]
802 );
803
804 $this->add_control(
805 'background_overlay_hover_opacity',
806 [
807 'label' => esc_html__( 'Opacity', 'elementor' ),
808 'type' => Controls_Manager::SLIDER,
809 'default' => [
810 'size' => .5,
811 ],
812 'range' => [
813 'px' => [
814 'max' => 1,
815 'step' => 0.01,
816 ],
817 ],
818 'selectors' => [
819 '{{WRAPPER}}:hover' => '--overlay-opacity: {{SIZE}};',
820 ],
821 'condition' => [
822 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
823 ],
824 ]
825 );
826
827 $this->add_group_control(
828 Group_Control_Css_Filter::get_type(),
829 [
830 'name' => 'css_filters_hover',
831 'selector' => '{{WRAPPER}}:hover::before',
832 ]
833 );
834
835 $this->add_control(
836 'background_overlay_hover_transition',
837 [
838 'label' => esc_html__( 'Transition Duration', 'elementor' ),
839 'type' => Controls_Manager::SLIDER,
840 'range' => [
841 'px' => [
842 'max' => 3,
843 'step' => 0.1,
844 ],
845 ],
846 'render_type' => 'ui',
847 'separator' => 'before',
848 'selectors' => [
849 '{{WRAPPER}}' => '--overlay-transition: {{SIZE}}s;',
850 ],
851 ]
852 );
853
854 $this->end_controls_tab();
855
856 $this->end_controls_tabs();
857
858 $this->end_controls_section();
859 }
860
861 /**
862 * Register the Container's border controls.
863 *
864 * @return void
865 */
866 protected function register_border_controls() {
867 $this->start_controls_section(
868 'section_border',
869 [
870 'label' => esc_html__( 'Border', 'elementor' ),
871 'tab' => Controls_Manager::TAB_STYLE,
872 ]
873 );
874
875 $this->start_controls_tabs( 'tabs_border' );
876
877 /**
878 * Normal.
879 */
880 $this->start_controls_tab(
881 'tab_border',
882 [
883 'label' => esc_html__( 'Normal', 'elementor' ),
884 ]
885 );
886
887 $this->add_group_control(
888 Group_Control_Border::get_type(),
889 [
890 'name' => 'border',
891 ]
892 );
893
894 $this->add_responsive_control(
895 'border_radius',
896 [
897 'label' => esc_html__( 'Border Radius', 'elementor' ),
898 'type' => Controls_Manager::DIMENSIONS,
899 'size_units' => [ 'px', '%', 'em' ],
900 'selectors' => [
901 '{{WRAPPER}}' => '--border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
902 ],
903 ]
904 );
905
906 $this->add_group_control(
907 Group_Control_Box_Shadow::get_type(),
908 [
909 'name' => 'box_shadow',
910 ]
911 );
912
913 $this->end_controls_tab();
914
915 /**
916 * Hover.
917 */
918 $this->start_controls_tab(
919 'tab_border_hover',
920 [
921 'label' => esc_html__( 'Hover', 'elementor' ),
922 ]
923 );
924
925 $this->add_group_control(
926 Group_Control_Border::get_type(),
927 [
928 'name' => 'border_hover',
929 'selector' => '{{WRAPPER}}:hover',
930 ]
931 );
932
933 $this->add_responsive_control(
934 'border_radius_hover',
935 [
936 'label' => esc_html__( 'Border Radius', 'elementor' ),
937 'type' => Controls_Manager::DIMENSIONS,
938 'size_units' => [ 'px', '%', 'em' ],
939 'selectors' => [
940 '{{WRAPPER}}:hover' => '--border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
941 ],
942 ]
943 );
944
945 $this->add_group_control(
946 Group_Control_Box_Shadow::get_type(),
947 [
948 'name' => 'box_shadow_hover',
949 'selector' => '{{WRAPPER}}:hover',
950 ]
951 );
952
953 $this->add_control(
954 'border_hover_transition',
955 [
956 'label' => esc_html__( 'Transition Duration', 'elementor' ),
957 'type' => Controls_Manager::SLIDER,
958 'separator' => 'before',
959 'default' => [
960 'size' => 0.3,
961 ],
962 'range' => [
963 'px' => [
964 'max' => 3,
965 'step' => 0.1,
966 ],
967 ],
968 'conditions' => [
969 'relation' => 'or',
970 'terms' => [
971 [
972 'name' => 'background_background',
973 'operator' => '!==',
974 'value' => '',
975 ],
976 [
977 'name' => 'border_border',
978 'operator' => '!==',
979 'value' => '',
980 ],
981 ],
982 ],
983 'selectors' => [
984 '{{WRAPPER}}' => '--transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s;
985 --overlay-transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
986 ],
987 ]
988 );
989
990 $this->end_controls_tab();
991
992 $this->end_controls_tabs();
993
994 $this->end_controls_section();
995 }
996
997 /**
998 * Register the Container's shape dividers controls.
999 * TODO: Copied from `section.php`.
1000 *
1001 * @return void
1002 */
1003 protected function register_shape_dividers_controls() {
1004 $this->start_controls_section(
1005 'section_shape_divider',
1006 [
1007 'label' => esc_html__( 'Shape Divider', 'elementor' ),
1008 'tab' => Controls_Manager::TAB_STYLE,
1009 ]
1010 );
1011
1012 $this->start_controls_tabs( 'tabs_shape_dividers' );
1013
1014 $shapes_options = [
1015 '' => esc_html__( 'None', 'elementor' ),
1016 ];
1017
1018 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
1019 $shapes_options[ $shape_name ] = $shape_props['title'];
1020 }
1021
1022 foreach ( [
1023 'top' => esc_html__( 'Top', 'elementor' ),
1024 'bottom' => esc_html__( 'Bottom', 'elementor' ),
1025 ] as $side => $side_label ) {
1026 $base_control_key = "shape_divider_$side";
1027
1028 $this->start_controls_tab(
1029 "tab_$base_control_key",
1030 [
1031 'label' => $side_label,
1032 ]
1033 );
1034
1035 $this->add_control(
1036 $base_control_key,
1037 [
1038 'label' => esc_html__( 'Type', 'elementor' ),
1039 'type' => Controls_Manager::SELECT,
1040 'options' => $shapes_options,
1041 'render_type' => 'none',
1042 'frontend_available' => true,
1043 ]
1044 );
1045
1046 $this->add_control(
1047 $base_control_key . '_color',
1048 [
1049 'label' => esc_html__( 'Color', 'elementor' ),
1050 'type' => Controls_Manager::COLOR,
1051 'condition' => [
1052 "shape_divider_$side!" => '',
1053 ],
1054 'selectors' => [
1055 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill, {{WRAPPER}} > .e-container__inner > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
1056 ],
1057 ]
1058 );
1059
1060 $this->add_responsive_control(
1061 $base_control_key . '_width',
1062 [
1063 'label' => esc_html__( 'Width', 'elementor' ),
1064 'type' => Controls_Manager::SLIDER,
1065 'default' => [
1066 'unit' => '%',
1067 ],
1068 'tablet_default' => [
1069 'unit' => '%',
1070 ],
1071 'mobile_default' => [
1072 'unit' => '%',
1073 ],
1074 'range' => [
1075 '%' => [
1076 'min' => 100,
1077 'max' => 300,
1078 ],
1079 ],
1080 'condition' => [
1081 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1082 ],
1083 'selectors' => [
1084 "{{WRAPPER}} > .elementor-shape-$side svg, {{WRAPPER}} > .e-container__inner > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1085 ],
1086 ]
1087 );
1088
1089 $this->add_responsive_control(
1090 $base_control_key . '_height',
1091 [
1092 'label' => esc_html__( 'Height', 'elementor' ),
1093 'type' => Controls_Manager::SLIDER,
1094 'range' => [
1095 'px' => [
1096 'max' => 500,
1097 ],
1098 ],
1099 'condition' => [
1100 "shape_divider_$side!" => '',
1101 ],
1102 'selectors' => [
1103 "{{WRAPPER}} > .elementor-shape-$side svg, {{WRAPPER}} > .e-container__inner > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1104 ],
1105 ]
1106 );
1107
1108 $this->add_control(
1109 $base_control_key . '_flip',
1110 [
1111 'label' => esc_html__( 'Flip', 'elementor' ),
1112 'type' => Controls_Manager::SWITCHER,
1113 'condition' => [
1114 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1115 ],
1116 'selectors' => [
1117 "{{WRAPPER}} > .elementor-shape-$side svg, {{WRAPPER}} > .e-container__inner > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1118 ],
1119 ]
1120 );
1121
1122 $this->add_control(
1123 $base_control_key . '_negative',
1124 [
1125 'label' => esc_html__( 'Invert', 'elementor' ),
1126 'type' => Controls_Manager::SWITCHER,
1127 'frontend_available' => true,
1128 'condition' => [
1129 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1130 ],
1131 'render_type' => 'none',
1132 ]
1133 );
1134
1135 $this->add_control(
1136 $base_control_key . '_above_content',
1137 [
1138 'label' => esc_html__( 'Bring to Front', 'elementor' ),
1139 'type' => Controls_Manager::SWITCHER,
1140 'selectors' => [
1141 "{{WRAPPER}} > .elementor-shape-$side, {{WRAPPER}} > .e-container__inner > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1142 ],
1143 'condition' => [
1144 "shape_divider_$side!" => '',
1145 ],
1146 ]
1147 );
1148
1149 $this->end_controls_tab();
1150 }
1151
1152 $this->end_controls_tabs();
1153
1154 $this->end_controls_section();
1155 }
1156 /**
1157 * Register the Container's style tab.
1158 *
1159 * @return void
1160 */
1161 protected function register_style_tab() {
1162 $this->register_background_controls();
1163
1164 $this->register_background_overlay_controls();
1165
1166 $this->register_border_controls();
1167
1168 $this->register_shape_dividers_controls();
1169 }
1170
1171 /**
1172 * Register the Container's advanced style controls.
1173 *
1174 * @return void
1175 */
1176 protected function register_advanced_controls() {
1177 $this->start_controls_section(
1178 'section_layout',
1179 [
1180 'label' => esc_html__( 'Layout', 'elementor' ),
1181 'tab' => Controls_Manager::TAB_ADVANCED,
1182 ]
1183 );
1184
1185 $this->add_responsive_control(
1186 'margin',
1187 [
1188 'label' => esc_html__( 'Margin', 'elementor' ),
1189 'type' => Controls_Manager::DIMENSIONS,
1190 'size_units' => [ 'px', 'em', '%', 'rem' ],
1191 'selectors' => [
1192 '{{WRAPPER}}' => '--margin-top: {{TOP}}{{UNIT}}; --margin-right: {{RIGHT}}{{UNIT}}; --margin-bottom: {{BOTTOM}}{{UNIT}}; --margin-left:{{LEFT}}{{UNIT}};',
1193 ],
1194 ]
1195 );
1196
1197 $this->add_responsive_control(
1198 'padding',
1199 [
1200 'label' => esc_html__( 'Padding', 'elementor' ),
1201 'type' => Controls_Manager::DIMENSIONS,
1202 'size_units' => [ 'px', 'em', '%', 'rem' ],
1203 'selectors' => [
1204 '{{WRAPPER}}' => '--padding-top: {{TOP}}{{UNIT}}; --padding-right: {{RIGHT}}{{UNIT}}; --padding-bottom: {{BOTTOM}}{{UNIT}}; --padding-left: {{LEFT}}{{UNIT}};',
1205 ],
1206 ]
1207 );
1208
1209 $this->add_group_control(
1210 Group_Control_Flex_Item::get_type(),
1211 [
1212 'name' => '_flex',
1213 'include' => [
1214 'align_self',
1215 'order',
1216 'order_custom',
1217 'size',
1218 'grow',
1219 'shrink',
1220 ],
1221 'selector' => '{{WRAPPER}}.e-container', // Hack to increase specificity.
1222 'separator' => 'before',
1223 ]
1224 );
1225
1226 $this->add_control(
1227 'position_description',
1228 [
1229 'raw' => '<strong>' . esc_html__( 'Please note!', 'elementor' ) . '</strong> ' . esc_html__( 'Custom positioning is not considered best practice for responsive web design and should not be used too frequently.', 'elementor' ),
1230 'type' => Controls_Manager::RAW_HTML,
1231 'content_classes' => 'elementor-panel-alert elementor-panel-alert-warning',
1232 'render_type' => 'ui',
1233 'condition' => [
1234 'position!' => '',
1235 ],
1236 ]
1237 );
1238
1239 // TODO: Copied from `common.php` - Extract to group control.
1240 $this->add_control(
1241 'position',
1242 [
1243 'label' => esc_html__( 'Position', 'elementor' ),
1244 'type' => Controls_Manager::SELECT,
1245 'default' => '',
1246 'options' => [
1247 '' => esc_html__( 'Default', 'elementor' ),
1248 'absolute' => esc_html__( 'Absolute', 'elementor' ),
1249 'fixed' => esc_html__( 'Fixed', 'elementor' ),
1250 ],
1251 'selectors' => [
1252 '{{WRAPPER}}' => '--position: {{VALUE}};',
1253 ],
1254 'frontend_available' => true,
1255 'separator' => 'before',
1256 ]
1257 );
1258
1259 $left = esc_html__( 'Left', 'elementor' );
1260 $right = esc_html__( 'Right', 'elementor' );
1261
1262 $start = is_rtl() ? $right : $left;
1263 $end = ! is_rtl() ? $right : $left;
1264
1265 $this->add_control(
1266 '_offset_orientation_h',
1267 [
1268 'label' => esc_html__( 'Horizontal Orientation', 'elementor' ),
1269 'type' => Controls_Manager::CHOOSE,
1270 'toggle' => false,
1271 'default' => 'start',
1272 'options' => [
1273 'start' => [
1274 'title' => $start,
1275 'icon' => 'eicon-h-align-left',
1276 ],
1277 'end' => [
1278 'title' => $end,
1279 'icon' => 'eicon-h-align-right',
1280 ],
1281 ],
1282 'classes' => 'elementor-control-start-end',
1283 'render_type' => 'ui',
1284 'condition' => [
1285 'position!' => '',
1286 ],
1287 ]
1288 );
1289
1290 $this->add_responsive_control(
1291 '_offset_x',
1292 [
1293 'label' => esc_html__( 'Offset', 'elementor' ),
1294 'type' => Controls_Manager::SLIDER,
1295 'range' => [
1296 'px' => [
1297 'min' => -1000,
1298 'max' => 1000,
1299 'step' => 1,
1300 ],
1301 '%' => [
1302 'min' => -200,
1303 'max' => 200,
1304 ],
1305 'vw' => [
1306 'min' => -200,
1307 'max' => 200,
1308 ],
1309 'vh' => [
1310 'min' => -200,
1311 'max' => 200,
1312 ],
1313 ],
1314 'default' => [
1315 'size' => '0',
1316 ],
1317 'size_units' => [ 'px', '%', 'vw', 'vh' ],
1318 'selectors' => [
1319 'body:not(.rtl) {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
1320 'body.rtl {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
1321 ],
1322 'condition' => [
1323 '_offset_orientation_h!' => 'end',
1324 'position!' => '',
1325 ],
1326 ]
1327 );
1328
1329 $this->add_responsive_control(
1330 '_offset_x_end',
1331 [
1332 'label' => esc_html__( 'Offset', 'elementor' ),
1333 'type' => Controls_Manager::SLIDER,
1334 'range' => [
1335 'px' => [
1336 'min' => -1000,
1337 'max' => 1000,
1338 'step' => 0.1,
1339 ],
1340 '%' => [
1341 'min' => -200,
1342 'max' => 200,
1343 ],
1344 'vw' => [
1345 'min' => -200,
1346 'max' => 200,
1347 ],
1348 'vh' => [
1349 'min' => -200,
1350 'max' => 200,
1351 ],
1352 ],
1353 'default' => [
1354 'size' => '0',
1355 ],
1356 'size_units' => [ 'px', '%', 'vw', 'vh' ],
1357 'selectors' => [
1358 'body:not(.rtl) {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
1359 'body.rtl {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
1360 ],
1361 'condition' => [
1362 '_offset_orientation_h' => 'end',
1363 'position!' => '',
1364 ],
1365 ]
1366 );
1367
1368 $this->add_control(
1369 '_offset_orientation_v',
1370 [
1371 'label' => esc_html__( 'Vertical Orientation', 'elementor' ),
1372 'type' => Controls_Manager::CHOOSE,
1373 'toggle' => false,
1374 'default' => 'start',
1375 'options' => [
1376 'start' => [
1377 'title' => esc_html__( 'Top', 'elementor' ),
1378 'icon' => 'eicon-v-align-top',
1379 ],
1380 'end' => [
1381 'title' => esc_html__( 'Bottom', 'elementor' ),
1382 'icon' => 'eicon-v-align-bottom',
1383 ],
1384 ],
1385 'render_type' => 'ui',
1386 'condition' => [
1387 'position!' => '',
1388 ],
1389 ]
1390 );
1391
1392 $this->add_responsive_control(
1393 '_offset_y',
1394 [
1395 'label' => esc_html__( 'Offset', 'elementor' ),
1396 'type' => Controls_Manager::SLIDER,
1397 'range' => [
1398 'px' => [
1399 'min' => -1000,
1400 'max' => 1000,
1401 'step' => 1,
1402 ],
1403 '%' => [
1404 'min' => -200,
1405 'max' => 200,
1406 ],
1407 'vh' => [
1408 'min' => -200,
1409 'max' => 200,
1410 ],
1411 'vw' => [
1412 'min' => -200,
1413 'max' => 200,
1414 ],
1415 ],
1416 'size_units' => [ 'px', '%', 'vh', 'vw' ],
1417 'default' => [
1418 'size' => '0',
1419 ],
1420 'selectors' => [
1421 '{{WRAPPER}}' => 'top: {{SIZE}}{{UNIT}}',
1422 ],
1423 'condition' => [
1424 '_offset_orientation_v!' => 'end',
1425 'position!' => '',
1426 ],
1427 ]
1428 );
1429
1430 $this->add_responsive_control(
1431 '_offset_y_end',
1432 [
1433 'label' => esc_html__( 'Offset', 'elementor' ),
1434 'type' => Controls_Manager::SLIDER,
1435 'range' => [
1436 'px' => [
1437 'min' => -1000,
1438 'max' => 1000,
1439 'step' => 1,
1440 ],
1441 '%' => [
1442 'min' => -200,
1443 'max' => 200,
1444 ],
1445 'vh' => [
1446 'min' => -200,
1447 'max' => 200,
1448 ],
1449 'vw' => [
1450 'min' => -200,
1451 'max' => 200,
1452 ],
1453 ],
1454 'size_units' => [ 'px', '%', 'vh', 'vw' ],
1455 'default' => [
1456 'size' => '0',
1457 ],
1458 'selectors' => [
1459 '{{WRAPPER}}' => 'bottom: {{SIZE}}{{UNIT}}',
1460 ],
1461 'condition' => [
1462 '_offset_orientation_v' => 'end',
1463 'position!' => '',
1464 ],
1465 ]
1466 );
1467
1468 $this->add_responsive_control(
1469 'z_index',
1470 [
1471 'label' => esc_html__( 'Z-Index', 'elementor' ),
1472 'type' => Controls_Manager::NUMBER,
1473 'min' => 0,
1474 'selectors' => [
1475 '{{WRAPPER}}' => '--z-index: {{VALUE}};',
1476 ],
1477 ]
1478 );
1479
1480 $this->add_control(
1481 '_element_id',
1482 [
1483 'label' => esc_html__( 'CSS ID', 'elementor' ),
1484 'type' => Controls_Manager::TEXT,
1485 'default' => '',
1486 'dynamic' => [
1487 'active' => true,
1488 ],
1489 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1490 'style_transfer' => false,
1491 'classes' => 'elementor-control-direction-ltr',
1492 ]
1493 );
1494
1495 $this->add_control(
1496 'css_classes',
1497 [
1498 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1499 'type' => Controls_Manager::TEXT,
1500 'default' => '',
1501 'dynamic' => [
1502 'active' => true,
1503 ],
1504 'prefix_class' => '',
1505 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1506 'classes' => 'elementor-control-direction-ltr',
1507 ]
1508 );
1509
1510 $this->end_controls_section();
1511 }
1512
1513 /**
1514 * Register the Container's motion effects controls.
1515 *
1516 * @return void
1517 */
1518 protected function register_motion_effects_controls() {
1519 $this->start_controls_section(
1520 'section_effects',
1521 [
1522 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1523 'tab' => Controls_Manager::TAB_ADVANCED,
1524 ]
1525 );
1526
1527 $this->add_responsive_control(
1528 'animation',
1529 [
1530 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1531 'type' => Controls_Manager::ANIMATION,
1532 'frontend_available' => true,
1533 ]
1534 );
1535
1536 $this->add_control(
1537 'animation_duration',
1538 [
1539 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1540 'type' => Controls_Manager::SELECT,
1541 'default' => '',
1542 'options' => [
1543 'slow' => esc_html__( 'Slow', 'elementor' ),
1544 '' => esc_html__( 'Normal', 'elementor' ),
1545 'fast' => esc_html__( 'Fast', 'elementor' ),
1546 ],
1547 'prefix_class' => 'animated-',
1548 'condition' => [
1549 'animation!' => '',
1550 ],
1551 ]
1552 );
1553
1554 $this->add_control(
1555 'animation_delay',
1556 [
1557 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1558 'type' => Controls_Manager::NUMBER,
1559 'default' => '',
1560 'min' => 0,
1561 'step' => 100,
1562 'condition' => [
1563 'animation!' => '',
1564 ],
1565 'render_type' => 'none',
1566 'frontend_available' => true,
1567 ]
1568 );
1569
1570 $this->end_controls_section();
1571 }
1572
1573 /**
1574 * Register the Container's responsive controls.
1575 *
1576 * @return void
1577 */
1578 protected function register_responsive_controls() {
1579 $this->start_controls_section(
1580 '_section_responsive',
1581 [
1582 'label' => esc_html__( 'Responsive', 'elementor' ),
1583 'tab' => Controls_Manager::TAB_ADVANCED,
1584 ]
1585 );
1586
1587 $this->add_control(
1588 'heading_visibility',
1589 [
1590 'label' => esc_html__( 'Visibility', 'elementor' ),
1591 'type' => Controls_Manager::HEADING,
1592 ]
1593 );
1594
1595 $this->add_control(
1596 'responsive_description',
1597 [
1598 'raw' => esc_html__( 'Responsive visibility will take effect only on preview or live page, and not while editing in Elementor.', 'elementor' ),
1599 'type' => Controls_Manager::RAW_HTML,
1600 'content_classes' => 'elementor-descriptor',
1601 ]
1602 );
1603
1604 $this->add_hidden_device_controls();
1605
1606 $this->end_controls_section();
1607 }
1608
1609 /**
1610 * Register the Container's advanced tab.
1611 *
1612 * @return void
1613 */
1614 protected function register_advanced_tab() {
1615 $this->register_advanced_controls();
1616
1617 $this->register_motion_effects_controls();
1618
1619 $this->register_responsive_controls();
1620
1621 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1622
1623 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1624 }
1625
1626 /**
1627 * Register the Container's controls.
1628 *
1629 * @return void
1630 */
1631 protected function register_controls() {
1632 $this->register_layout_tab();
1633 $this->register_style_tab();
1634 $this->register_advanced_tab();
1635 }
1636 }
1637