PluginProbe
Elementor Website Builder – more than just a page builder / 3.19.4
Elementor Website Builder – more than just a page builder v3.19.4
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 / widgets / common.php

common.php in Elementor Website Builder – more than just a page builder 3.19.4, at includes/widgets/common.php

1,176 lines 28.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Core\Breakpoints\Manager as Breakpoints_Manager;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor common widget.
12 *
13 * Elementor base widget that gives you all the advanced options of the basic
14 * widget.
15 *
16 * @since 1.0.0
17 */
18 class Widget_Common extends Widget_Base {
19
20 /**
21 * Get widget name.
22 *
23 * Retrieve common widget name.
24 *
25 * @since 1.0.0
26 * @access public
27 *
28 * @return string Widget name.
29 */
30 public function get_name() {
31 return 'common';
32 }
33
34 /**
35 * Show in panel.
36 *
37 * Whether to show the common widget in the panel or not.
38 *
39 * @since 1.0.0
40 * @access public
41 *
42 * @return bool Whether to show the widget in the panel.
43 */
44 public function show_in_panel() {
45 return false;
46 }
47
48 /**
49 * Get Responsive Device Args
50 *
51 * Receives an array of device args, and duplicates it for each active breakpoint.
52 * Returns an array of device args.
53 *
54 * @since 3.4.7
55 * @deprecated 3.7.0 Not needed anymore because responsive conditioning in the Editor was fixed in v3.7.0.
56 * @access protected
57 *
58 * @param array $args arguments to duplicate per breakpoint
59 * @param array $devices_to_exclude
60 *
61 * @return array responsive device args
62 */
63 protected function get_responsive_device_args( array $args, array $devices_to_exclude = [] ) {
64 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.7.0' );
65
66 $device_args = [];
67 $breakpoints = Plugin::$instance->breakpoints->get_active_breakpoints();
68
69 foreach ( $breakpoints as $breakpoint_key => $breakpoint ) {
70 // If the device is not excluded, add it to the device args array.
71 if ( ! in_array( $breakpoint_key, $devices_to_exclude, true ) ) {
72 $parsed_device_args = $this->parse_device_args_placeholders( $args, $breakpoint_key );
73
74 $device_args[ $breakpoint_key ] = $parsed_device_args;
75 }
76 }
77
78 return $device_args;
79 }
80
81 /**
82 * Parse Device Args Placeholders
83 *
84 * Receives an array of args. Iterates over the args, and replaces the {{DEVICE}} placeholder, if exists, with the
85 * passed breakpoint key.
86 *
87 * @since 3.4.7
88 * @access private
89 *
90 * @param array $args
91 * @param string $breakpoint_key
92 * @return array parsed device args
93 */
94 private function parse_device_args_placeholders( array $args, $breakpoint_key ) {
95 $parsed_args = [];
96
97 foreach ( $args as $arg_key => $arg_value ) {
98 $arg_key = str_replace( '{{DEVICE}}', $breakpoint_key, $arg_key );
99
100 if ( is_array( $arg_value ) ) {
101 $arg_value = $this->parse_device_args_placeholders( $arg_value, $breakpoint_key );
102 }
103
104 $parsed_args[ $arg_key ] = $arg_value;
105 }
106
107 return $parsed_args;
108 }
109
110 /**
111 * @param $shape String Shape name.
112 *
113 * @return string The shape path in the assets folder.
114 */
115 private function get_shape_url( $shape ) {
116 return ELEMENTOR_ASSETS_URL . 'mask-shapes/' . $shape . '.svg';
117 }
118
119 /**
120 * Return a translated user-friendly list of the available masking shapes.
121 *
122 * @param bool $add_custom Determine if the output should contain `Custom` options.
123 *
124 * @return array Array of shapes with their URL as key.
125 */
126 private function get_shapes( $add_custom = true ) {
127 $shapes = [
128 'circle' => esc_html__( 'Circle', 'elementor' ),
129 'flower' => esc_html__( 'Flower', 'elementor' ),
130 'sketch' => esc_html__( 'Sketch', 'elementor' ),
131 'triangle' => esc_html__( 'Triangle', 'elementor' ),
132 'blob' => esc_html__( 'Blob', 'elementor' ),
133 'hexagon' => esc_html__( 'Hexagon', 'elementor' ),
134 ];
135
136 if ( $add_custom ) {
137 $shapes['custom'] = esc_html__( 'Custom', 'elementor' );
138 }
139
140 return $shapes;
141 }
142
143 /**
144 * Gets a string of CSS rules to apply, and returns an array of selectors with those rules.
145 * This function has been created in order to deal with masking for image widget.
146 * For most of the widgets the mask is being applied to the wrapper itself, but in the case of an image widget,
147 * the `img` tag should be masked directly. So instead of writing a lot of selectors every time,
148 * this function builds both of those selectors easily.
149 *
150 * @param $rules string The CSS rules to apply.
151 *
152 * @return array Selectors with the rules applied.
153 */
154 private function get_mask_selectors( $rules ) {
155 $mask_selectors = [
156 'default' => '{{WRAPPER}}:not( .elementor-widget-image ) .elementor-widget-container',
157 'image' => '{{WRAPPER}}.elementor-widget-image .elementor-widget-container img',
158 ];
159
160 return [
161 $mask_selectors['default'] => $rules,
162 $mask_selectors['image'] => $rules,
163 ];
164 }
165
166 /**
167 * Register the Layout section.
168 *
169 * @return void
170 */
171 private function register_layout_section() {
172 $this->start_controls_section(
173 '_section_style',
174 [
175 'label' => esc_html__( 'Layout', 'elementor' ),
176 'tab' => Controls_Manager::TAB_ADVANCED,
177 ]
178 );
179
180 // Element Name for the Navigator
181 $this->add_control(
182 '_title',
183 [
184 'label' => esc_html__( 'Title', 'elementor' ),
185 'type' => Controls_Manager::HIDDEN,
186 'render_type' => 'none',
187 ]
188 );
189
190 $this->add_responsive_control(
191 '_margin',
192 [
193 'label' => esc_html__( 'Margin', 'elementor' ),
194 'type' => Controls_Manager::DIMENSIONS,
195 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
196 'selectors' => [
197 '{{WRAPPER}} > .elementor-widget-container' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
198 ],
199 ]
200 );
201
202 $this->add_responsive_control(
203 '_padding',
204 [
205 'label' => esc_html__( 'Padding', 'elementor' ),
206 'type' => Controls_Manager::DIMENSIONS,
207 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
208 'selectors' => [
209 '{{WRAPPER}} > .elementor-widget-container' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
210 ],
211 ]
212 );
213
214 $experiments_manager = Plugin::$instance->experiments;
215 $is_container_active = $experiments_manager->is_feature_active( 'container' );
216
217 $this->add_responsive_control(
218 '_element_width',
219 [
220 'label' => esc_html__( 'Width', 'elementor' ),
221 'type' => Controls_Manager::SELECT,
222 'default' => '',
223 'options' => [
224 '' => esc_html__( 'Default', 'elementor' ),
225 'inherit' => esc_html__( 'Full Width', 'elementor' ) . ' (100%)',
226 'auto' => esc_html__( 'Inline', 'elementor' ) . ' (auto)',
227 'initial' => esc_html__( 'Custom', 'elementor' ),
228 ],
229 'selectors_dictionary' => [
230 'inherit' => '100%',
231 ],
232 'prefix_class' => 'elementor-widget%s__width-',
233 'selectors' => [
234 '{{WRAPPER}}' => 'width: {{VALUE}}; max-width: {{VALUE}}',
235 ],
236 ]
237 );
238
239 $this->add_responsive_control(
240 '_element_custom_width',
241 [
242 'label' => esc_html__( 'Custom Width', 'elementor' ),
243 'type' => Controls_Manager::SLIDER,
244 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
245 'default' => [
246 'unit' => '%',
247 ],
248 'range' => [
249 'px' => [
250 'max' => 1000,
251 ],
252 ],
253 'selectors' => [
254 '{{WRAPPER}}' => '--container-widget-width: {{SIZE}}{{UNIT}}; --container-widget-flex-grow: 0; width: var( --container-widget-width, {{SIZE}}{{UNIT}} ); max-width: {{SIZE}}{{UNIT}}',
255 ],
256 'condition' => [ '_element_width' => 'initial' ],
257 ]
258 );
259
260 // Register Flex controls only if the Container experiment is active.
261 if ( $is_container_active ) {
262 $this->add_group_control(
263 Group_Control_Flex_Item::get_type(),
264 [
265 'name' => '_flex',
266 // Hack to increase specificity and make sure that the current widget overrides the
267 // parent flex settings.
268 'selector' => '{{WRAPPER}}.elementor-element',
269 'include' => [
270 'align_self',
271 'order',
272 'order_custom',
273 'size',
274 'grow',
275 'shrink',
276 ],
277 'fields_options' => [
278 'align_self' => [
279 'separator' => 'before',
280 ],
281 ],
282 ]
283 );
284 }
285
286 $vertical_align_conditions = [
287 '_element_width!' => '',
288 '_position' => '',
289 ];
290
291 if ( $is_container_active ) {
292 $vertical_align_conditions['_element_vertical_align!'] = ''; // TODO: For BC.
293 }
294
295 // TODO: For BC - Remove in the future.
296 $this->add_responsive_control(
297 '_element_vertical_align',
298 [
299 'label' => esc_html__( 'Vertical Align', 'elementor' ),
300 'type' => Controls_Manager::CHOOSE,
301 'options' => [
302 'flex-start' => [
303 'title' => esc_html__( 'Start', 'elementor' ),
304 'icon' => 'eicon-v-align-top',
305 ],
306 'center' => [
307 'title' => esc_html__( 'Center', 'elementor' ),
308 'icon' => 'eicon-v-align-middle',
309 ],
310 'flex-end' => [
311 'title' => esc_html__( 'End', 'elementor' ),
312 'icon' => 'eicon-v-align-bottom',
313 ],
314 ],
315 'condition' => $vertical_align_conditions,
316 'selectors' => [
317 '{{WRAPPER}}' => 'align-self: {{VALUE}}',
318 ],
319 ]
320 );
321
322 $this->add_control(
323 '_position_description',
324 [
325 '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' ),
326 'type' => Controls_Manager::RAW_HTML,
327 'content_classes' => 'elementor-panel-alert elementor-panel-alert-warning',
328 'render_type' => 'ui',
329 'condition' => [
330 '_position!' => '',
331 ],
332 ]
333 );
334
335 $this->add_control(
336 '_position',
337 [
338 'label' => esc_html__( 'Position', 'elementor' ),
339 'type' => Controls_Manager::SELECT,
340 'default' => '',
341 'options' => [
342 '' => esc_html__( 'Default', 'elementor' ),
343 'absolute' => esc_html__( 'Absolute', 'elementor' ),
344 'fixed' => esc_html__( 'Fixed', 'elementor' ),
345 ],
346 'prefix_class' => 'elementor-',
347 'frontend_available' => true,
348 'separator' => 'before',
349 ]
350 );
351
352 $start = is_rtl() ? esc_html__( 'Right', 'elementor' ) : esc_html__( 'Left', 'elementor' );
353 $end = ! is_rtl() ? esc_html__( 'Right', 'elementor' ) : esc_html__( 'Left', 'elementor' );
354
355 $this->add_control(
356 '_offset_orientation_h',
357 [
358 'label' => esc_html__( 'Horizontal Orientation', 'elementor' ),
359 'type' => Controls_Manager::CHOOSE,
360 'toggle' => false,
361 'default' => 'start',
362 'options' => [
363 'start' => [
364 'title' => $start,
365 'icon' => 'eicon-h-align-left',
366 ],
367 'end' => [
368 'title' => $end,
369 'icon' => 'eicon-h-align-right',
370 ],
371 ],
372 'classes' => 'elementor-control-start-end',
373 'render_type' => 'ui',
374 'condition' => [
375 '_position!' => '',
376 ],
377 ]
378 );
379
380 $this->add_responsive_control(
381 '_offset_x',
382 [
383 'label' => esc_html__( 'Offset', 'elementor' ),
384 'type' => Controls_Manager::SLIDER,
385 'range' => [
386 'px' => [
387 'min' => -1000,
388 'max' => 1000,
389 ],
390 '%' => [
391 'min' => -200,
392 'max' => 200,
393 ],
394 'vw' => [
395 'min' => -200,
396 'max' => 200,
397 ],
398 'vh' => [
399 'min' => -200,
400 'max' => 200,
401 ],
402 ],
403 'default' => [
404 'size' => 0,
405 ],
406 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'vh', 'custom' ],
407 'selectors' => [
408 'body:not(.rtl) {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
409 'body.rtl {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
410 ],
411 'condition' => [
412 '_offset_orientation_h!' => 'end',
413 '_position!' => '',
414 ],
415 ]
416 );
417
418 $this->add_responsive_control(
419 '_offset_x_end',
420 [
421 'label' => esc_html__( 'Offset', 'elementor' ),
422 'type' => Controls_Manager::SLIDER,
423 'range' => [
424 'px' => [
425 'min' => -1000,
426 'max' => 1000,
427 ],
428 '%' => [
429 'min' => -200,
430 'max' => 200,
431 ],
432 'vw' => [
433 'min' => -200,
434 'max' => 200,
435 ],
436 'vh' => [
437 'min' => -200,
438 'max' => 200,
439 ],
440 ],
441 'default' => [
442 'size' => 0,
443 ],
444 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'vh', 'custom' ],
445 'selectors' => [
446 'body:not(.rtl) {{WRAPPER}}' => 'right: {{SIZE}}{{UNIT}}',
447 'body.rtl {{WRAPPER}}' => 'left: {{SIZE}}{{UNIT}}',
448 ],
449 'condition' => [
450 '_offset_orientation_h' => 'end',
451 '_position!' => '',
452 ],
453 ]
454 );
455
456 $this->add_control(
457 '_offset_orientation_v',
458 [
459 'label' => esc_html__( 'Vertical Orientation', 'elementor' ),
460 'type' => Controls_Manager::CHOOSE,
461 'toggle' => false,
462 'default' => 'start',
463 'options' => [
464 'start' => [
465 'title' => esc_html__( 'Top', 'elementor' ),
466 'icon' => 'eicon-v-align-top',
467 ],
468 'end' => [
469 'title' => esc_html__( 'Bottom', 'elementor' ),
470 'icon' => 'eicon-v-align-bottom',
471 ],
472 ],
473 'render_type' => 'ui',
474 'condition' => [
475 '_position!' => '',
476 ],
477 ]
478 );
479
480 $this->add_responsive_control(
481 '_offset_y',
482 [
483 'label' => esc_html__( 'Offset', 'elementor' ),
484 'type' => Controls_Manager::SLIDER,
485 'range' => [
486 'px' => [
487 'min' => -1000,
488 'max' => 1000,
489 ],
490 '%' => [
491 'min' => -200,
492 'max' => 200,
493 ],
494 'vh' => [
495 'min' => -200,
496 'max' => 200,
497 ],
498 'vw' => [
499 'min' => -200,
500 'max' => 200,
501 ],
502 ],
503 'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'vw', 'custom' ],
504 'default' => [
505 'size' => 0,
506 ],
507 'selectors' => [
508 '{{WRAPPER}}' => 'top: {{SIZE}}{{UNIT}}',
509 ],
510 'condition' => [
511 '_offset_orientation_v!' => 'end',
512 '_position!' => '',
513 ],
514 ]
515 );
516
517 $this->add_responsive_control(
518 '_offset_y_end',
519 [
520 'label' => esc_html__( 'Offset', 'elementor' ),
521 'type' => Controls_Manager::SLIDER,
522 'range' => [
523 'px' => [
524 'min' => -1000,
525 'max' => 1000,
526 ],
527 '%' => [
528 'min' => -200,
529 'max' => 200,
530 ],
531 'vh' => [
532 'min' => -200,
533 'max' => 200,
534 ],
535 'vw' => [
536 'min' => -200,
537 'max' => 200,
538 ],
539 ],
540 'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'vw', 'custom' ],
541 'default' => [
542 'size' => 0,
543 ],
544 'selectors' => [
545 '{{WRAPPER}}' => 'bottom: {{SIZE}}{{UNIT}}',
546 ],
547 'condition' => [
548 '_offset_orientation_v' => 'end',
549 '_position!' => '',
550 ],
551 ]
552 );
553
554 $this->add_responsive_control(
555 '_z_index',
556 [
557 'label' => esc_html__( 'Z-Index', 'elementor' ),
558 'type' => Controls_Manager::NUMBER,
559 'selectors' => [
560 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
561 ],
562 ]
563 );
564
565 $this->add_control(
566 '_element_id',
567 [
568 'label' => esc_html__( 'CSS ID', 'elementor' ),
569 'type' => Controls_Manager::TEXT,
570 'dynamic' => [
571 'active' => true,
572 ],
573 'ai' => [
574 'active' => false,
575 ],
576 'default' => '',
577 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
578 'style_transfer' => false,
579 'classes' => 'elementor-control-direction-ltr',
580 ]
581 );
582
583 $this->add_control(
584 '_css_classes',
585 [
586 'label' => esc_html__( 'CSS Classes', 'elementor' ),
587 'type' => Controls_Manager::TEXT,
588 'ai' => [
589 'active' => false,
590 ],
591 'dynamic' => [
592 'active' => true,
593 ],
594 'prefix_class' => '',
595 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
596 'classes' => 'elementor-control-direction-ltr',
597 ]
598 );
599
600 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
601
602 $this->end_controls_section();
603 }
604
605 /**
606 * Register the Motion Effects section.
607 *
608 * @return void
609 */
610 private function register_effects_section() {
611 $this->start_controls_section(
612 'section_effects',
613 [
614 'label' => esc_html__( 'Motion Effects', 'elementor' ),
615 'tab' => Controls_Manager::TAB_ADVANCED,
616 ]
617 );
618
619 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
620
621 $this->add_responsive_control(
622 '_animation',
623 [
624 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
625 'type' => Controls_Manager::ANIMATION,
626 'frontend_available' => true,
627 ]
628 );
629
630 $this->add_control(
631 'animation_duration',
632 [
633 'label' => esc_html__( 'Animation Duration', 'elementor' ),
634 'type' => Controls_Manager::SELECT,
635 'default' => '',
636 'options' => [
637 'slow' => esc_html__( 'Slow', 'elementor' ),
638 '' => esc_html__( 'Normal', 'elementor' ),
639 'fast' => esc_html__( 'Fast', 'elementor' ),
640 ],
641 'prefix_class' => 'animated-',
642 'condition' => [
643 '_animation!' => '',
644 ],
645 ]
646 );
647
648 $this->add_control(
649 '_animation_delay',
650 [
651 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
652 'type' => Controls_Manager::NUMBER,
653 'default' => '',
654 'min' => 0,
655 'step' => 100,
656 'condition' => [
657 '_animation!' => '',
658 ],
659 'render_type' => 'none',
660 'frontend_available' => true,
661 ]
662 );
663
664 $this->end_controls_section();
665 }
666
667 /** Register the Background section.
668 *
669 * @return void
670 */
671 private function register_background_section() {
672 $this->start_controls_section(
673 '_section_background',
674 [
675 'label' => esc_html__( 'Background', 'elementor' ),
676 'tab' => Controls_Manager::TAB_ADVANCED,
677 ]
678 );
679
680 $this->start_controls_tabs( '_tabs_background' );
681
682 $this->start_controls_tab(
683 '_tab_background_normal',
684 [
685 'label' => esc_html__( 'Normal', 'elementor' ),
686 ]
687 );
688
689 $this->add_group_control(
690 Group_Control_Background::get_type(),
691 [
692 'name' => '_background',
693 'selector' => '{{WRAPPER}} > .elementor-widget-container',
694 'fields_options' => [
695 'image' => [
696 'background_lazyload' => [
697 'active' => true,
698 'keys' => [ '_background_image', 'url' ],
699 'selector' => '.elementor-widget-container',
700 ],
701 ],
702 ],
703 ]
704 );
705
706 $this->end_controls_tab();
707
708 $this->start_controls_tab(
709 '_tab_background_hover',
710 [
711 'label' => esc_html__( 'Hover', 'elementor' ),
712 ]
713 );
714
715 $this->add_group_control(
716 Group_Control_Background::get_type(),
717 [
718 'name' => '_background_hover',
719 'selector' => '{{WRAPPER}}:hover .elementor-widget-container',
720 ]
721 );
722
723 $this->add_control(
724 '_background_hover_transition',
725 [
726 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
727 'type' => Controls_Manager::SLIDER,
728 'range' => [
729 'px' => [
730 'min' => 0,
731 'max' => 3,
732 'step' => 0.1,
733 ],
734 ],
735 'render_type' => 'ui',
736 'separator' => 'before',
737 'selectors' => [
738 '{{WRAPPER}} > .elementor-widget-container' => 'transition: background {{SIZE}}s',
739 ],
740 ]
741 );
742
743 $this->end_controls_tab();
744
745 $this->end_controls_tabs();
746
747 $this->end_controls_section();
748 }
749
750 /**
751 * Register the Border section.
752 *
753 * @return void
754 */
755 private function register_border_section() {
756 $this->start_controls_section(
757 '_section_border',
758 [
759 'label' => esc_html__( 'Border', 'elementor' ),
760 'tab' => Controls_Manager::TAB_ADVANCED,
761 ]
762 );
763
764 $this->start_controls_tabs( '_tabs_border' );
765
766 $this->start_controls_tab(
767 '_tab_border_normal',
768 [
769 'label' => esc_html__( 'Normal', 'elementor' ),
770 ]
771 );
772
773 $this->add_group_control(
774 Group_Control_Border::get_type(),
775 [
776 'name' => '_border',
777 'selector' => '{{WRAPPER}} > .elementor-widget-container',
778 ]
779 );
780
781 $this->add_responsive_control(
782 '_border_radius',
783 [
784 'label' => esc_html__( 'Border Radius', 'elementor' ),
785 'type' => Controls_Manager::DIMENSIONS,
786 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
787 'selectors' => [
788 '{{WRAPPER}} > .elementor-widget-container' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
789 ],
790 ]
791 );
792
793 $this->add_group_control(
794 Group_Control_Box_Shadow::get_type(),
795 [
796 'name' => '_box_shadow',
797 'selector' => '{{WRAPPER}} > .elementor-widget-container',
798 ]
799 );
800
801 $this->end_controls_tab();
802
803 $this->start_controls_tab(
804 '_tab_border_hover',
805 [
806 'label' => esc_html__( 'Hover', 'elementor' ),
807 ]
808 );
809
810 $this->add_group_control(
811 Group_Control_Border::get_type(),
812 [
813 'name' => '_border_hover',
814 'selector' => '{{WRAPPER}}:hover .elementor-widget-container',
815 ]
816 );
817
818 $this->add_responsive_control(
819 '_border_radius_hover',
820 [
821 'label' => esc_html__( 'Border Radius', 'elementor' ),
822 'type' => Controls_Manager::DIMENSIONS,
823 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
824 'selectors' => [
825 '{{WRAPPER}}:hover > .elementor-widget-container' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
826 ],
827 ]
828 );
829
830 $this->add_group_control(
831 Group_Control_Box_Shadow::get_type(),
832 [
833 'name' => '_box_shadow_hover',
834 'selector' => '{{WRAPPER}}:hover .elementor-widget-container',
835 ]
836 );
837
838 $this->add_control(
839 '_border_hover_transition',
840 [
841 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
842 'type' => Controls_Manager::SLIDER,
843 'separator' => 'before',
844 'range' => [
845 'px' => [
846 'min' => 0,
847 'max' => 3,
848 'step' => 0.1,
849 ],
850 ],
851 'selectors' => [
852 '{{WRAPPER}} .elementor-widget-container' => 'transition: background {{_background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
853 ],
854 ]
855 );
856
857 $this->end_controls_tab();
858
859 $this->end_controls_tabs();
860
861 $this->end_controls_section();
862 }
863
864
865 /**
866 * Register the Mask section.
867 *
868 * @return void
869 */
870 private function register_masking_section() {
871 $this->start_controls_section(
872 '_section_masking',
873 [
874 'label' => esc_html__( 'Mask', 'elementor' ),
875 'tab' => Controls_Manager::TAB_ADVANCED,
876 ]
877 );
878
879 $this->add_control(
880 '_mask_switch',
881 [
882 'label' => esc_html__( 'Mask', 'elementor' ),
883 'type' => Controls_Manager::SWITCHER,
884 'label_on' => esc_html__( 'On', 'elementor' ),
885 'label_off' => esc_html__( 'Off', 'elementor' ),
886 'default' => '',
887 ]
888 );
889
890 $this->add_control(
891 '_mask_shape',
892 [
893 'label' => esc_html__( 'Shape', 'elementor' ),
894 'type' => Controls_Manager::SELECT,
895 'options' => $this->get_shapes(),
896 'default' => 'circle',
897 'selectors' => $this->get_mask_selectors( '-webkit-mask-image: url( ' . ELEMENTOR_ASSETS_URL . '/mask-shapes/{{VALUE}}.svg );' ),
898 'condition' => [
899 '_mask_switch!' => '',
900 ],
901 ]
902 );
903
904 $this->add_control(
905 '_mask_image',
906 [
907 'label' => esc_html__( 'Image', 'elementor' ),
908 'type' => Controls_Manager::MEDIA,
909 'media_types' => [ 'image' ],
910 'should_include_svg_inline_option' => true,
911 'library_type' => 'image/svg+xml',
912 'dynamic' => [
913 'active' => true,
914 ],
915 'selectors' => $this->get_mask_selectors( '-webkit-mask-image: url( {{URL}} );' ),
916 'condition' => [
917 '_mask_switch!' => '',
918 '_mask_shape' => 'custom',
919 ],
920 ]
921 );
922
923 $this->add_control(
924 '_mask_notice',
925 [
926 'type' => Controls_Manager::HIDDEN,
927 'raw' => esc_html__( 'Need More Shapes?', 'elementor' ) .
928 '<br>' .
929 sprintf(
930 /* translators: 1: Link open tag, 2: Link close tag. */
931 esc_html__( 'Explore additional Premium Shape packs and use them in your site. %1$sLearn More%2$s', 'elementor' ),
932 '<a target="_blank" href="https://go.elementor.com/mask-control">',
933 '</a>'
934 ),
935 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
936 'condition' => [
937 '_mask_switch!' => '',
938 ],
939 ]
940 );
941
942 $this->add_responsive_control(
943 '_mask_size',
944 [
945 'label' => esc_html__( 'Size', 'elementor' ),
946 'type' => Controls_Manager::SELECT,
947 'options' => [
948 'contain' => esc_html__( 'Fit', 'elementor' ),
949 'cover' => esc_html__( 'Fill', 'elementor' ),
950 'custom' => esc_html__( 'Custom', 'elementor' ),
951 ],
952 'default' => 'contain',
953 'selectors' => $this->get_mask_selectors( '-webkit-mask-size: {{VALUE}};' ),
954 'condition' => [
955 '_mask_switch!' => '',
956 ],
957 ]
958 );
959
960 $this->add_responsive_control(
961 '_mask_size_scale',
962 [
963 'label' => esc_html__( 'Scale', 'elementor' ),
964 'type' => Controls_Manager::SLIDER,
965 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
966 'range' => [
967 'px' => [
968 'min' => 0,
969 'max' => 500,
970 ],
971 'em' => [
972 'min' => 0,
973 'max' => 100,
974 ],
975 '%' => [
976 'min' => 0,
977 'max' => 200,
978 ],
979 ],
980 'default' => [
981 'unit' => '%',
982 'size' => 100,
983 ],
984 'selectors' => $this->get_mask_selectors( '-webkit-mask-size: {{SIZE}}{{UNIT}};' ),
985 'condition' => [
986 '_mask_switch!' => '',
987 '_mask_size' => 'custom',
988 ],
989 ]
990 );
991
992 $this->add_responsive_control(
993 '_mask_position',
994 [
995 'label' => esc_html__( 'Position', 'elementor' ),
996 'type' => Controls_Manager::SELECT,
997 'options' => [
998 'center center' => esc_html__( 'Center Center', 'elementor' ),
999 'center left' => esc_html__( 'Center Left', 'elementor' ),
1000 'center right' => esc_html__( 'Center Right', 'elementor' ),
1001 'top center' => esc_html__( 'Top Center', 'elementor' ),
1002 'top left' => esc_html__( 'Top Left', 'elementor' ),
1003 'top right' => esc_html__( 'Top Right', 'elementor' ),
1004 'bottom center' => esc_html__( 'Bottom Center', 'elementor' ),
1005 'bottom left' => esc_html__( 'Bottom Left', 'elementor' ),
1006 'bottom right' => esc_html__( 'Bottom Right', 'elementor' ),
1007 'custom' => esc_html__( 'Custom', 'elementor' ),
1008 ],
1009 'default' => 'center center',
1010 'selectors' => $this->get_mask_selectors( '-webkit-mask-position: {{VALUE}};' ),
1011 'condition' => [
1012 '_mask_switch!' => '',
1013 ],
1014 ]
1015 );
1016
1017 $this->add_responsive_control(
1018 '_mask_position_x',
1019 [
1020 'label' => esc_html__( 'X Position', 'elementor' ),
1021 'type' => Controls_Manager::SLIDER,
1022 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1023 'range' => [
1024 'px' => [
1025 'min' => -500,
1026 'max' => 500,
1027 ],
1028 'em' => [
1029 'min' => -100,
1030 'max' => 100,
1031 ],
1032 '%' => [
1033 'min' => -100,
1034 'max' => 100,
1035 ],
1036 'vw' => [
1037 'min' => -100,
1038 'max' => 100,
1039 ],
1040 ],
1041 'default' => [
1042 'unit' => '%',
1043 'size' => 0,
1044 ],
1045 'selectors' => $this->get_mask_selectors( '-webkit-mask-position-x: {{SIZE}}{{UNIT}};' ),
1046 'condition' => [
1047 '_mask_switch!' => '',
1048 '_mask_position' => 'custom',
1049 ],
1050 ]
1051 );
1052
1053 $this->add_responsive_control(
1054 '_mask_position_y',
1055 [
1056 'label' => esc_html__( 'Y Position', 'elementor' ),
1057 'type' => Controls_Manager::SLIDER,
1058 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1059 'range' => [
1060 'px' => [
1061 'min' => -500,
1062 'max' => 500,
1063 ],
1064 'em' => [
1065 'min' => -100,
1066 'max' => 100,
1067 ],
1068 '%' => [
1069 'min' => -100,
1070 'max' => 100,
1071 ],
1072 'vw' => [
1073 'min' => -100,
1074 'max' => 100,
1075 ],
1076 ],
1077 'default' => [
1078 'unit' => '%',
1079 'size' => 0,
1080 ],
1081 'selectors' => $this->get_mask_selectors( '-webkit-mask-position-y: {{SIZE}}{{UNIT}};' ),
1082 'condition' => [
1083 '_mask_switch!' => '',
1084 '_mask_position' => 'custom',
1085 ],
1086 ]
1087 );
1088
1089 $this->add_responsive_control(
1090 '_mask_repeat',
1091 [
1092 'label' => esc_html__( 'Repeat', 'elementor' ),
1093 'type' => Controls_Manager::SELECT,
1094 'options' => [
1095 'no-repeat' => esc_html__( 'No-repeat', 'elementor' ),
1096 'repeat' => esc_html__( 'Repeat', 'elementor' ),
1097 'repeat-x' => esc_html__( 'Repeat-x', 'elementor' ),
1098 'repeat-Y' => esc_html__( 'Repeat-y', 'elementor' ),
1099 'round' => esc_html__( 'Round', 'elementor' ),
1100 'space' => esc_html__( 'Space', 'elementor' ),
1101 ],
1102 'default' => 'no-repeat',
1103 'selectors' => $this->get_mask_selectors( '-webkit-mask-repeat: {{VALUE}};' ),
1104 'condition' => [
1105 '_mask_switch!' => '',
1106 '_mask_size!' => 'cover',
1107 ],
1108 ]
1109 );
1110
1111 $this->end_controls_section();
1112 }
1113
1114
1115 /**
1116 * Register the Responsive section.
1117 *
1118 * @return void
1119 */
1120 private function register_responsive_section() {
1121 $this->start_controls_section(
1122 '_section_responsive',
1123 [
1124 'label' => esc_html__( 'Responsive', 'elementor' ),
1125 'tab' => Controls_Manager::TAB_ADVANCED,
1126 ]
1127 );
1128
1129 $this->add_control(
1130 'responsive_description',
1131 [
1132 'raw' => sprintf(
1133 /* translators: 1: Link open tag, 2: Link close tag. */
1134 esc_html__( 'Responsive visibility will take effect only on %1$s preview mode %2$s or live page, and not while editing in Elementor.', 'elementor' ),
1135 '<a href="javascript: $e.run( \'panel/close\' )">',
1136 '</a>'
1137 ),
1138 'type' => Controls_Manager::RAW_HTML,
1139 'content_classes' => 'elementor-descriptor',
1140 ]
1141 );
1142
1143 $this->add_hidden_device_controls();
1144
1145 $this->end_controls_section();
1146 }
1147
1148 /**
1149 * Register common widget controls.
1150 *
1151 * Adds different input fields to allow the user to change and customize the widget settings.
1152 *
1153 * @since 3.1.0
1154 * @access protected
1155 */
1156 protected function register_controls() {
1157 $this->register_layout_section();
1158
1159 $this->register_effects_section();
1160
1161 $this->register_transform_section();
1162
1163 $this->register_background_section();
1164
1165 $this->register_border_section();
1166
1167 $this->register_masking_section();
1168
1169 $this->register_responsive_section();
1170
1171 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1172
1173 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1174 }
1175 }
1176