This commit is contained in:
proelements
2025-12-29 10:01:13 +02:00
parent ce77bab1a1
commit 9bdad9d028
319 changed files with 1925 additions and 658 deletions

View File

@@ -312,20 +312,25 @@ class Animated_Headline extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-headline' => 'text-align: {{VALUE}}',
],

View File

@@ -0,0 +1,55 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets;
use ElementorPro\Base\Module_Base;
use ElementorPro\Plugin;
use Elementor\Modules\AtomicWidgets\Module as AtomicWidgetsModule;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers_Registry;
use ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions\Display_Conditions_Prop_Type;
use ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions\Condition_Group_Prop_Type;
use ElementorPro\Modules\AtomicWidgets\Transformers\Display_Conditions as Display_Conditions_Transformer;
use ElementorPro\Modules\AtomicWidgets\Transformers\Condition_Group as Condition_Group_Transformer;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class Module extends Module_Base {
public function get_name() {
return 'atomic';
}
public function __construct() {
parent::__construct();
if ( ! Plugin::elementor()->experiments->is_feature_active( AtomicWidgetsModule::EXPERIMENT_NAME ) ) {
return;
}
add_filter(
'elementor/atomic-widgets/props-schema',
fn( $schema ) => $this->inject_props_schema( $schema ),
10,
1
);
add_action(
'elementor/atomic-widgets/settings/transformers/register',
fn ( $transformers ) => $this->register_settings_transformers( $transformers ),
);
}
private function inject_props_schema( $schema ) {
$schema[ Display_Conditions_Prop_Type::get_key() ] = Display_Conditions_Prop_Type::make();
return $schema;
}
private function register_settings_transformers( Transformers_Registry $transformers ): Transformers_Registry {
$transformers->register( Display_Conditions_Prop_Type::get_key(), new Display_Conditions_Transformer() );
$transformers->register( Condition_Group_Prop_Type::get_key(), new Condition_Group_Transformer() );
return $transformers;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions;
use Elementor\Modules\AtomicWidgets\PropTypes\Base\Array_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Contracts\Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Condition_Group_Prop_Type extends Array_Prop_Type {
public static function get_key(): string {
return 'condition-group';
}
protected function define_item_type(): Prop_Type {
return String_Prop_Type::make();
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions;
use Elementor\Modules\AtomicWidgets\PropTypes\Base\Array_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Contracts\Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Display_Conditions_Prop_Type extends Array_Prop_Type {
public static function get_key(): string {
return 'display-conditions';
}
protected function define_item_type(): Prop_Type {
return Condition_Group_Prop_Type::make();
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions;
use Elementor\Modules\AtomicWidgets\PropTypes\Base\Object_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Page_Title_Condition_Prop_Type extends Object_Prop_Type {
public static function get_key(): string {
return 'page-title-condition';
}
protected function validate_value( $value ): bool {
return true;
}
protected function define_shape(): array {
return [
'operator' => String_Prop_Type::make()
->enum( [ '==', '!=' ] )
->default( '==' )
->required(),
'value' => String_Prop_Type::make()
->required(),
];
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions;
use Elementor\Modules\AtomicWidgets\PropTypes\Base\Object_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Date_Time_Prop_Type;
use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\Boolean_Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Time_Of_Day_Condition_Prop_Type extends Object_Prop_Type {
public static function get_key(): string {
return 'time-of-day-condition';
}
protected function validate_value( $value ): bool {
return true;
}
protected function define_shape(): array {
return [
'operator' => String_Prop_Type::make()
->enum( [ '==', '!=', '>', '<', '>=', '<=' ] )
->default( '==' )
->required(),
'server_time' => Boolean_Prop_Type::make()
->default( true )
->required(),
'value' => Date_Time_Prop_Type::make()
->required(),
];
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\Transformers;
use Elementor\Modules\AtomicWidgets\PropsResolver\Props_Resolver_Context;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformer_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Condition_Group extends Transformer_Base {
public function transform( $conditions, Props_Resolver_Context $context ) {
if ( ! is_array( $conditions ) || empty( $conditions ) ) {
return null;
}
return array_map( function( $condition ) {
return json_decode( $condition, true );
}, $conditions );
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace ElementorPro\Modules\AtomicWidgets\Transformers;
use Elementor\Modules\AtomicWidgets\PropsResolver\Props_Resolver_Context;
use Elementor\Modules\AtomicWidgets\PropsResolver\Render_Props_Resolver;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformer_Base;
use ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions\Display_Conditions_Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Display_Conditions extends Transformer_Base {
public function transform( $value, Props_Resolver_Context $context ) {
return ! is_array( $value ) || empty( $value )
? []
: $value;
}
public static function extract_from_settings( $settings ) {
$prop_key = Display_Conditions_Prop_Type::get_key();
if ( ! isset( $settings[ $prop_key ]['value'] ) ) {
return '[]';
}
$params = self::create_params_from_settings( $settings );
$resolved = Render_Props_Resolver::for_settings()->resolve( ...$params );
return [ json_encode( $resolved[ $prop_key ] ) ];
}
private static function create_params_from_settings( $settings ) {
$prop_key = Display_Conditions_Prop_Type::get_key();
$prop_type = Display_Conditions_Prop_Type::make();
$value = $settings[ $prop_key ];
$schema = [
$prop_key => $prop_type,
];
$props = [
$prop_key => $value,
];
return [ $schema, $props ];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace ElementorPro\Modules\Attributes\Controls;
use Elementor\Modules\AtomicWidgets\Controls\Types\Repeatable_Control as Core_Repeatable_Control;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Repeatable_Attributes_Control extends Core_Repeatable_Control {
private ?array $add_item_tooltip_props = null;
public function set_addItemTooltipProps( array $props ): self {
$this->add_item_tooltip_props = $props;
return $this;
}
public function get_props(): array {
$props = parent::get_props();
if ( null !== $this->add_item_tooltip_props ) {
$props['addItemTooltipProps'] = (object) $this->add_item_tooltip_props;
}
return $props;
}
}

View File

@@ -3,8 +3,10 @@ namespace ElementorPro\Modules\Attributes;
use ElementorPro\Base\Module_Base;
use ElementorPro\License\API;
use Elementor\Modules\AtomicWidgets\Controls\Types\Repeatable_Control;
use ElementorPro\Modules\Attributes\Controls\Repeatable_Attributes_Control;
use Elementor\Modules\AtomicWidgets\Controls\Section;
use Elementor\Modules\AtomicWidgets\PropTypes\Attributes_Prop_Type;
use ElementorPro\Modules\Attributes\PropsResolver\Transformers\Settings\Pro_Attributes_Transformer;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
@@ -20,10 +22,26 @@ class Module extends Module_Base {
return API::is_licence_has_feature( 'atomic-custom-attributes' );
}
private function is_license_expired() {
return API::is_license_expired();
}
public function __construct() {
parent::__construct();
if ( $this->is_attributes_active() ) {
if ( $this->is_attributes_active() || $this->is_license_expired() ) {
add_action(
'elementor/atomic-widgets/settings/transformers/register',
function ( $transformers ) {
$attributes_key = Attributes_Prop_Type::get_key();
$transformers->register(
$attributes_key,
new Pro_Attributes_Transformer()
);
},
20
);
add_filter(
'elementor/atomic-widgets/controls',
fn( $element_controls, $atomic_element ) => $this->inject_attrs_control( $element_controls, $atomic_element ),
@@ -35,14 +53,17 @@ class Module extends Module_Base {
private function inject_attrs_control( $element_controls, $atomic_element ) {
$schema = $atomic_element::get_props_schema();
if ( ! array_key_exists( 'attributes', $schema ) || ! class_exists( '\\Elementor\\Modules\\AtomicWidgets\\PropTypes\\Attributes_Prop_Type' ) ) {
if ( ! array_key_exists( 'attributes', $schema ) ) {
return $element_controls;
}
foreach ( $element_controls as $item ) {
if ( $item instanceof Section && $item->get_id() === 'settings' ) {
$control = Repeatable_Control::bind_to( 'attributes' )
->set_meta( [ 'topDivider' => true ] )
$is_empty_controls = empty( $item->get_items() );
$control = Repeatable_Attributes_Control::bind_to( 'attributes' )
->set_meta( [ 'topDivider' => ! $is_empty_controls ] )
->set_repeaterLabel( __( 'Attributes', 'elementor-pro' ) )
->set_initialValues(
[
@@ -67,6 +88,14 @@ class Module extends Module_Base {
$control->set_prop_key( 'attributes' );
}
if ( $this->is_license_expired() || ! $this->is_attributes_active() ) {
$control
->set_addItemTooltipProps( [
'disabled' => true,
] )
->set_child_control_props( (object) [ 'readOnly' => true ] );
}
$item->add_item( $control );
break;
}

View File

@@ -0,0 +1,36 @@
<?php
namespace ElementorPro\Modules\Attributes\PropsResolver\Transformers\Settings;
use Elementor\Modules\AtomicWidgets\PropsResolver\Props_Resolver_Context;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformer_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Pro_Attributes_Transformer extends Transformer_Base {
public function transform( $value, Props_Resolver_Context $context ) {
if ( ! is_array( $value ) ) {
return null;
}
$result = implode( ' ', array_map( function ( $item ) {
if ( ! $this->is_valid_attribute_item( $item ) ) {
return '';
}
$escaped_value = esc_attr( $item['value'] );
return $item['key'] . '="' . $escaped_value . '"';
}, $value ) );
return $result;
}
private function is_valid_attribute_item( $item ): bool {
return isset( $item['key'], $item['value'] )
&& '' !== $item['key']
&& '' !== $item['value'];
}
}

View File

@@ -435,20 +435,25 @@ class Call_To_Action extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-cta__content' => 'text-align: {{VALUE}}',
],

View File

@@ -419,6 +419,7 @@ class Countdown extends Base_Widget {
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors' => [
'{{WRAPPER}} .elementor-countdown-wrapper' => 'text-align: {{VALUE}};',
],
@@ -649,19 +650,24 @@ class Countdown extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-countdown-expire--message' => 'text-align: {{VALUE}};',
],

View File

@@ -0,0 +1,32 @@
<?php
namespace ElementorPro\Modules\DisplayConditions;
use Elementor\Modules\AtomicWidgets\Base\Atomic_Control_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Display_Conditions_Control extends Atomic_Control_Base {
private ?bool $disabled = null;
public function get_type(): string {
return 'display-conditions';
}
public function set_disabled( bool $disabled ): self {
$this->disabled = $disabled;
return $this;
}
public function get_props(): array {
$props = [];
if ( null !== $this->disabled ) {
$props['disabled'] = $this->disabled;
}
return $props;
}
}

View File

@@ -5,8 +5,11 @@ use Elementor\Controls_Manager;
use Elementor\Utils;
use ElementorPro\Base\Module_Base;
use ElementorPro\License\API;
use ElementorPro\Modules\AtomicWidgets\Transformers\Display_Conditions as Display_Conditions_Transformer;
use ElementorPro\Modules\DisplayConditions\Classes\Or_Condition;
use ElementorPro\Plugin;
use Elementor\Modules\AtomicWidgets\Controls\Section;
use ElementorPro\Modules\AtomicWidgets\PropTypes\Display_Conditions\Display_Conditions_Prop_Type;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
@@ -14,6 +17,7 @@ if ( ! defined( 'ABSPATH' ) ) {
class Module extends Module_Base {
private $hidden_elements_ids = [];
const LICENSE_FEATURE_NAME = 'display-conditions';
@@ -27,6 +31,42 @@ class Module extends Module_Base {
}
$this->maybe_add_actions_and_components();
add_filter(
'elementor/atomic-widgets/controls',
fn( $element_controls, $atomic_element ) => $this->inject_display_conditions_control( $element_controls, $atomic_element ),
100,
2
);
}
private function inject_display_conditions_control( $element_controls, $atomic_element ) {
$schema = $atomic_element::get_props_schema();
if ( ! array_key_exists( Display_Conditions_Prop_Type::get_key(), $schema ) ) {
return $element_controls;
}
foreach ( $element_controls as $item ) {
if ( $item instanceof Section && $item->get_id() === 'settings' ) {
$control = Display_Conditions_Control::bind_to( Display_Conditions_Prop_Type::get_key() )
->set_label( __( 'Display Conditions', 'elementor-pro' ) )
->set_meta( [
'topDivider' => true,
] );
if ( API::is_license_expired() ) {
$control->set_disabled( true );
}
$item->add_item( $control );
break;
}
}
return $element_controls;
}
public static function should_show_promo(): bool {
@@ -75,6 +115,15 @@ class Module extends Module_Base {
true
);
$inline_script = sprintf(
'window.ElementorProDisplayConditions = %s;',
wp_json_encode( [
'isLicenseExpired' => API::is_license_expired(),
] )
);
wp_add_inline_script( 'e-display-conditions', $inline_script, 'before' );
wp_set_script_translations( 'e-display-conditions', 'elementor-pro' );
}
@@ -162,9 +211,13 @@ class Module extends Module_Base {
}
protected function get_saved_conditions( $settings ) {
$conditions_json = ! empty( $settings['e_display_conditions'] ) ? $settings['e_display_conditions'] : [];
if ( isset( $settings[ Display_Conditions_Prop_Type::get_key() ] ) ) {
$settings['e_display_conditions'] = Display_Conditions_Transformer::extract_from_settings( $settings );
}
return ! empty( $conditions_json ) && ! empty( $conditions_json[0] )
$conditions_json = ! empty( $settings['e_display_conditions'] ) ? $settings['e_display_conditions'] : '[]';
return ! empty( $conditions_json )
? json_decode( $conditions_json[0], true )
: [];
}
@@ -174,7 +227,7 @@ class Module extends Module_Base {
$is_visible = true;
$saved_conditions = $this->get_saved_conditions( $settings );
if ( empty( $settings['e_display_conditions'] ) || Plugin::elementor()->editor->is_edit_mode() || empty( $saved_conditions ) ) {
if ( Plugin::elementor()->editor->is_edit_mode() || empty( $saved_conditions ) ) {
return $is_visible;
}

View File

@@ -34,12 +34,10 @@ class Contact_URL extends Tag {
'label' => esc_html__( 'Type', 'elementor-pro' ),
'type' => Controls_Manager::SELECT,
'options' => [
'' => '— ' . esc_html__( 'Select', 'elementor-pro' ) . ' —',
'email' => esc_html__( 'Email', 'elementor-pro' ),
'tel' => esc_html__( 'Tel', 'elementor-pro' ),
'sms' => esc_html__( 'SMS', 'elementor-pro' ),
'whatsapp' => esc_html__( 'WhatsApp', 'elementor-pro' ),
'skype' => esc_html__( 'Skype', 'elementor-pro' ),
'messenger' => esc_html__( 'Messenger', 'elementor-pro' ),
'viber' => esc_html__( 'Viber', 'elementor-pro' ),
'waze' => esc_html__( 'Waze', 'elementor-pro' ),
@@ -136,25 +134,6 @@ class Contact_URL extends Tag {
]
);
$this->add_control(
'skype_action',
[
'label' => esc_html__( 'Action', 'elementor-pro' ),
'type' => Controls_Manager::SELECT,
'options' => [
'call' => esc_html__( 'Call', 'elementor-pro' ),
'chat' => esc_html__( 'Chat', 'elementor-pro' ),
'userinfo' => esc_html__( 'Show Profile', 'elementor-pro' ),
'add' => esc_html__( 'Add to Contacts', 'elementor-pro' ),
'voicemail' => esc_html__( 'Send Voice Mail', 'elementor-pro' ),
],
'default' => 'call',
'condition' => [
'link_type' => 'skype',
],
]
);
$this->add_control(
'waze_address',
[
@@ -290,19 +269,6 @@ class Contact_URL extends Tag {
return 'https://api.whatsapp.com/send?phone=' . $settings['tel_number'];
}
private function build_skype_link( $settings ) {
if ( empty( $settings['username'] ) ) {
return '';
}
$action = 'call';
if ( ! empty( $settings['skype_action'] ) ) {
$action = $settings['skype_action'];
}
$link = 'skype:' . $settings['username'] . '?' . $action;
return $link;
}
private function build_waze_link( $settings ) {
$link = 'https://waze.com/ul?';
@@ -318,6 +284,10 @@ class Contact_URL extends Tag {
private function date_to_iso( $date, $all_day = false ) {
$time = strtotime( $date );
if ( false === $time ) {
return '';
}
if ( $all_day ) {
return gmdate( 'Ymd\/Ymd', $time );
}
@@ -340,7 +310,9 @@ class Contact_URL extends Tag {
if ( empty( $settings['event_end_date'] ) ) {
$dates = $this->date_to_iso( $settings['event_start_date'], true );
} else {
$dates = $this->date_to_iso( $settings['event_start_date'] ) . '/' . $this->date_to_iso( $settings['event_end_date'] );
$start = $this->date_to_iso( $settings['event_start_date'] );
$end = $this->date_to_iso( $settings['event_end_date'] );
$dates = $start && $end ? ( $start . '/' . $end ) : ( $start ? $start : ( $end ? $end : '' ) );
}
}
$link = 'https://www.google.com/calendar/render?action=TEMPLATE&';
@@ -436,9 +408,6 @@ class Contact_URL extends Tag {
case 'whatsapp':
$value = $this->build_whatsapp_link( $settings );
break;
case 'skype':
$value = $this->build_skype_link( $settings );
break;
case 'waze':
$value = $this->build_waze_link( $settings );
break;

View File

@@ -504,20 +504,25 @@ class Flip_Box extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-flip-box__front .elementor-flip-box__layer__overlay' => 'text-align: {{VALUE}}',
],
@@ -1129,23 +1134,28 @@ class Flip_Box extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-flip-box__back .elementor-flip-box__layer__overlay' => 'text-align: {{VALUE}}',
'{{WRAPPER}} .elementor-flip-box__button' => 'margin-{{VALUE}}: 0',
'{{WRAPPER}} .elementor-flip-box__button' => 'margin-inline-{{VALUE}}: 0',
],
]
);
@@ -1587,6 +1597,7 @@ class Flip_Box extends Base_Widget {
$title_tag = Utils::validate_html_tag( $settings['title_tag'] );
$description_tag = Utils::validate_html_tag( $settings['description_tag'] );
$migration_allowed = Icons_Manager::is_migration_allowed();
$this->add_render_attribute( 'button', 'class', [
'elementor-flip-box__button',
'elementor-button',
@@ -1620,14 +1631,19 @@ class Flip_Box extends Base_Widget {
}
if ( ! empty( $settings['icon'] ) ) {
$this->add_render_attribute( 'icon', 'class', $settings['icon'] );
$this->add_render_attribute(
'icon',
[
'class' => $settings['icon'],
'aria-hidden' => 'true',
]
);
}
}
$has_icon = ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon'] );
$migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
$is_new = empty( $settings['icon'] ) && $migration_allowed;
?>
<div class="elementor-flip-box" tabindex="0">
<div class="elementor-flip-box__layer elementor-flip-box__front">
@@ -1641,7 +1657,7 @@ class Flip_Box extends Base_Widget {
<div <?php $this->print_render_attribute_string( 'icon-wrapper' ); ?>>
<div class="elementor-icon">
<?php if ( $is_new || $migrated ) :
Icons_Manager::render_icon( $settings['selected_icon'] );
Icons_Manager::render_icon( $settings['selected_icon'], [ 'aria-hidden' => 'true' ] );
else : ?>
<i <?php $this->print_render_attribute_string( 'icon' ); ?>></i>
<?php endif; ?>
@@ -1736,7 +1752,6 @@ class Flip_Box extends Base_Widget {
iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
#>
<div class="elementor-flip-box" tabindex="0">
<div class="elementor-flip-box__layer elementor-flip-box__front">
<div class="elementor-flip-box__layer__overlay">
@@ -1751,7 +1766,7 @@ class Flip_Box extends Base_Widget {
<# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
{{{ iconHTML.value }}}
<# } else { #>
<i class="{{ settings.icon }}"></i>
<i class="{{ settings.icon }}" aria-hidden="true"></i>
<# } #>
</div>
</div>

View File

@@ -35,7 +35,7 @@ class Note_Query_Builder extends Model_Query_Builder {
*
* @param \wpdb|null $connection
*/
public function __construct( \wpdb $connection = null ) {
public function __construct( ?\wpdb $connection = null ) {
parent::__construct( Note::class, $connection );
}
@@ -72,7 +72,7 @@ class Note_Query_Builder extends Model_Query_Builder {
*
* @return $this
*/
public function with_replies( callable $callback = null ) {
public function with_replies( ?callable $callback = null ) {
$key = 'replies';
$foreign_key = 'parent_id';
$local_key = 'id';

View File

@@ -256,20 +256,25 @@ abstract class Posts_Base extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-pagination' => 'text-align: {{VALUE}};',
],

View File

@@ -993,19 +993,24 @@ class Price_Table extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-price-table__features-list' => 'text-align: {{VALUE}}',
],

View File

@@ -443,19 +443,24 @@ class Slides extends Base_Widget {
'label' => esc_html__( 'Text Align', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} {{CURRENT_ITEM}} .swiper-slide-inner' => 'text-align: {{VALUE}}',
],
@@ -859,20 +864,25 @@ class Slides extends Base_Widget {
'label' => esc_html__( 'Text Align', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'default' => 'center',
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .swiper-slide-inner' => 'text-align: {{VALUE}}',
],

View File

@@ -545,9 +545,6 @@ class Table_Of_Contents extends Base_Widget {
]
);
$logical_start = is_rtl() ? 'right' : 'left';
$logical_end = is_rtl() ? 'left' : 'right';
$this->add_responsive_control(
'header_text_align',
[
@@ -556,7 +553,7 @@ class Table_Of_Contents extends Base_Widget {
'options' => [
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => "eicon-text-align-$logical_start",
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
@@ -564,10 +561,11 @@ class Table_Of_Contents extends Base_Widget {
],
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => "eicon-text-align-$logical_end",
'icon' => 'eicon-text-align-right',
],
],
'default' => 'start',
'classes' => 'elementor-control-start-end',
'selectors' => [
'{{WRAPPER}} .elementor-toc__header-title' => 'text-align: {{VALUE}}',
],
@@ -633,15 +631,16 @@ class Table_Of_Contents extends Base_Widget {
'options' => [
'row-reverse' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => "eicon-h-align-$logical_start",
'icon' => 'eicon-h-align-left',
],
'row' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => "eicon-h-align-$logical_end",
'icon' => 'eicon-h-align-right',
],
],
'default' => 'row',
'toggle' => false,
'classes' => 'elementor-control-start-end',
'selectors' => [
'{{WRAPPER}} .elementor-toc__header' => 'flex-direction: {{VALUE}};',
],

View File

@@ -56,16 +56,16 @@ class Post_Content extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
@@ -73,6 +73,11 @@ class Post_Content extends Base_Widget {
'icon' => 'eicon-text-align-justify',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}};',
],

View File

@@ -79,16 +79,16 @@ class Post_Excerpt extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
@@ -96,6 +96,11 @@ class Post_Excerpt extends Base_Widget {
'icon' => 'eicon-text-align-justify',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
"{{WRAPPER}}{$widget_container_selector}" => 'text-align: {{VALUE}};',
],

View File

@@ -204,19 +204,24 @@ class Search_Form extends Base {
'type' => Controls_Manager::CHOOSE,
'default' => 'center',
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-h-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-h-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-h-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .elementor-search-form' => 'text-align: {{VALUE}}',
],

View File

@@ -0,0 +1,80 @@
<?php
namespace ElementorPro\Modules\Transitions;
use ElementorPro\Base\Module_Base;
use ElementorPro\License\API;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class Module extends Module_Base {
public function get_name() {
return 'transitions';
}
private function is_transitions_active() {
return API::is_licence_has_feature( 'transitions' );
}
public function __construct() {
parent::__construct();
if ( $this->is_transitions_active() ) {
add_filter(
'elementor/atomic-widgets/styles/transitions/allowed-properties',
[ $this, 'extend_allowed_properties' ]
);
}
}
public function extend_allowed_properties( array $core_properties ): array {
$pro_properties = [
'margin',
'margin-block-end',
'margin-inline-start',
'margin-inline-end',
'margin-block-start',
'padding',
'padding-block-end',
'padding-inline-start',
'padding-inline-end',
'padding-block-start',
'flex',
'flex-grow',
'flex-shrink',
'flex-basis',
'width',
'height',
'max-height',
'max-width',
'min-height',
'min-width',
'top',
'left',
'bottom',
'right',
'z-index',
'color',
'font-size',
'line-height',
'letter-spacing',
'word-spacing',
'font-variation-settings',
'-webkit-text-stroke-color',
'background-color',
'background-position',
'box-shadow',
'border',
'border-radius',
'border-color',
'border-width',
'opacity',
'transform',
'filter',
];
return array_merge( $core_properties, $pro_properties );
}
}

View File

@@ -81,24 +81,16 @@ class Style_Schema {
}
private function update_union( Union_Prop_Type $union_prop_type ): Union_Prop_Type {
$new_union = Union_Prop_Type::make();
$dependencies = $union_prop_type->get_dependencies();
$new_union->set_dependencies( $dependencies );
foreach ( $union_prop_type->get_prop_types() as $prop_type ) {
$updated = $this->update( $prop_type );
if ( $updated instanceof Union_Prop_Type ) {
foreach ( $updated->get_prop_types() as $updated_prop_type ) {
$new_union->add_prop_type( $updated_prop_type );
$union_prop_type->add_prop_type( $updated_prop_type );
}
continue;
}
$new_union->add_prop_type( $updated );
}
return $new_union;
return $union_prop_type;
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace ElementorPro\Modules\Woocommerce\ImportExportCustomization;
use Elementor\App\Modules\ImportExportCustomization\Runners\Revert\Revert_Runner_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Woocommerce_Settings_Revert extends Revert_Runner_Base {
public static function get_name(): string {
return 'woocommerce-settings';
}
public function should_revert( array $data ): bool {
return isset( $data['runners'][ static::get_name() ] );
}
public function revert( array $data ) {
$runner_data = $data['runners'][ static::get_name() ];
$previous_pages = $runner_data['previous_pages'] ?? [];
foreach ( $previous_pages as $key => $value ) {
update_option( $key, $value );
}
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace ElementorPro\Modules\Woocommerce\ImportExportCustomization;
use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Import_Runner_Base;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Woocommerce_Settings extends Import_Runner_Base {
const KEYS_TO_IMPORT = [
'woocommerce_cart_page_id',
'woocommerce_checkout_page_id',
'woocommerce_myaccount_page_id',
'woocommerce_terms_page_id',
'elementor_woocommerce_purchase_summary_page_id',
'woocommerce_shop_page_id',
];
private $old_values = [];
private $imported_pages = [];
public static function get_name(): string {
return 'woocommerce-settings';
}
public function should_import( array $data ) {
return (
isset( $data['include'] ) &&
in_array( 'settings', $data['include'], true ) &&
! empty( $data['site_settings']['settings'] )
);
}
public function import( array $data, array $imported_data ) {
$new_site_settings = $data['site_settings']['settings'];
$pages = $imported_data['content']['page']['succeed'] ?? [];
$imported = false;
foreach ( self::KEYS_TO_IMPORT as $key ) {
$value = $new_site_settings[ $key ] ?? null;
if ( isset( $pages[ $value ] ) ) {
$page = $pages[ $value ];
$this->old_values[ $key ] = get_option( $key );
$update_result = update_option( $key, $page );
if ( $update_result ) {
$this->imported_pages[ $key ] = $page;
$imported = true;
}
}
}
return [ static::get_name() => $imported ];
}
public function get_import_session_metadata(): array {
return [
'previous_pages' => $this->old_values,
'imported_pages' => $this->imported_pages,
];
}
}

View File

@@ -21,6 +21,10 @@ use ElementorPro\Modules\Woocommerce\Widgets\Products as Products_Widget;
use Elementor\Icons_Manager;
use ElementorPro\Modules\LoopBuilder\Module as LoopBuilderModule;
use ElementorPro\License\API;
use Elementor\App\Modules\ImportExportCustomization\Processes\Import;
use Elementor\App\Modules\ImportExportCustomization\Processes\Revert;
use ElementorPro\Modules\Woocommerce\ImportExportCustomization\Woocommerce_Settings;
use ElementorPro\Modules\Woocommerce\ImportExportCustomization\Woocommerce_Settings_Revert;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
@@ -1360,9 +1364,20 @@ class Module extends Module_Base {
return Plugin::elementor()->preview->is_preview_mode() || is_preview();
}
public function register_import_runner( Import $import ) {
$import->register( new Woocommerce_Settings() );
}
public function register_revert_runner( Revert $revert ) {
$revert->register( new Woocommerce_Settings_Revert() );
}
public function __construct() {
parent::__construct();
add_action( 'elementor/import-export-customization/import-kit', [ $this, 'register_import_runner' ] );
add_action( 'elementor/import-export-customization/revert-kit', [ $this, 'register_revert_runner' ] );
add_action( 'elementor/kit/register_tabs', [ $this, 'init_site_settings' ], 1, 40 );
$this->add_update_kit_settings_hooks();

View File

@@ -62,16 +62,16 @@ class Archive_Description extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
@@ -79,6 +79,11 @@ class Archive_Description extends Base_Widget {
'icon' => 'eicon-text-align-justify',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}}',
],

View File

@@ -90,19 +90,24 @@ class Breadcrumb extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}} .woocommerce-breadcrumb' => 'text-align: {{VALUE}}',
],

View File

@@ -72,19 +72,24 @@ class Product_Price extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}}',
],

View File

@@ -169,19 +169,24 @@ class Product_Related extends Products_Base {
'label' => esc_html__( 'Text Align', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'.woocommerce {{WRAPPER}}.elementor-wc-products .products > h2' => 'text-align: {{VALUE}}',
],

View File

@@ -56,16 +56,16 @@ class Product_Short_Description extends Base_Widget {
'label' => esc_html__( 'Alignment', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
'justify' => [
@@ -73,6 +73,11 @@ class Product_Short_Description extends Base_Widget {
'icon' => 'eicon-text-align-justify',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}}' => 'text-align: {{VALUE}}',
],

View File

@@ -156,19 +156,24 @@ class Product_Upsell extends Products_Base {
'label' => esc_html__( 'Text Align', 'elementor-pro' ),
'type' => Controls_Manager::CHOOSE,
'options' => [
'left' => [
'title' => esc_html__( 'Left', 'elementor-pro' ),
'start' => [
'title' => esc_html__( 'Start', 'elementor-pro' ),
'icon' => 'eicon-text-align-left',
],
'center' => [
'title' => esc_html__( 'Center', 'elementor-pro' ),
'icon' => 'eicon-text-align-center',
],
'right' => [
'title' => esc_html__( 'Right', 'elementor-pro' ),
'end' => [
'title' => esc_html__( 'End', 'elementor-pro' ),
'icon' => 'eicon-text-align-right',
],
],
'classes' => 'elementor-control-start-end',
'selectors_dictionary' => [
'left' => is_rtl() ? 'end' : 'start',
'right' => is_rtl() ? 'start' : 'end',
],
'selectors' => [
'{{WRAPPER}}.elementor-wc-products .products > h2' => 'text-align: {{VALUE}}',
],