PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 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 All 452 releases
elementor / modules / atomic-widgets / module.php

module.php in Elementor Website Builder – more than just a page builder 4.3.0-beta3, at modules/atomic-widgets/module.php

735 lines 41.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\AtomicWidgets;
4
5 use Elementor\Core\Base\Module as BaseModule;
6 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
7 use Elementor\Core\Experiments\Manager as Experiments_Manager;
8 use Elementor\Elements_Manager;
9 use Elementor\Modules\AtomicWidgets\Ajax\Render_Element_Action;
10 use Elementor\Modules\AtomicWidgets\DynamicTags\Dynamic_Prop_Type;
11 use Elementor\Modules\AtomicWidgets\DynamicTags\Dynamic_Tags_Module;
12 use Elementor\Modules\AtomicWidgets\PlainResolvers\Plain_Resolvers_Registry;
13 use Elementor\Modules\AtomicWidgets\PlainResolvers\Plain_Values_Resolver;
14 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Boolean_Plain_Resolver;
15 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Dynamic_Plain_Resolver;
16 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Passthrough_Plain_Resolver;
17 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Number_Plain_Resolver;
18 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Size_Plain_Resolver;
19 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\String_Plain_Resolver;
20 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Youtube\Atomic_Youtube;
21 use Elementor\Modules\AtomicWidgets\Elements\Div_Block\Div_Block;
22 use Elementor\Modules\AtomicWidgets\Elements\Flexbox\Flexbox;
23 use Elementor\Modules\AtomicWidgets\Elements\Grid\Grid;
24 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Heading\Atomic_Heading;
25 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Image\Atomic_Image;
26 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Paragraph\Atomic_Paragraph;
27 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Button\Atomic_Button;
28 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Divider\Atomic_Divider;
29 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Svg\Atomic_Svg;
30 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion;
31 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item\Atomic_Accordion_Item;
32 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Content\Atomic_Accordion_Item_Content;
33 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Header\Atomic_Accordion_Item_Header;
34 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Icon\Atomic_Accordion_Item_Icon;
35 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Title\Atomic_Accordion_Item_Title;
36 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs\Atomic_Tabs;
37 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs_Menu\Atomic_Tabs_Menu;
38 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tab\Atomic_Tab;
39 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs_Content_Area\Atomic_Tabs_Content_Area;
40 use Elementor\Modules\AtomicWidgets\ImportExport\Atomic_Import_Export;
41 use Elementor\Modules\AtomicWidgets\Elements\Promotions\Pro_Promotion_Data_Preservation;
42 use Elementor\Modules\AtomicWidgets\Elements\Loader\Frontend_Assets_Loader;
43 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Combine_Array_Transformer;
44 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Export\Image_Src_Export_Transformer;
45 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Export\Svg_Src_Export_Transformer;
46 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Image_Src_Transformer;
47 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Image_Transformer;
48 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import\Image_Src_Import_Transformer;
49 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import\Svg_Src_Import_Transformer;
50 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Icon_Transformer;
51 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Svg_Src_Transformer;
52 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import_Export_Plain_Transformer;
53 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Classes_Transformer;
54 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Date_Time_Transformer;
55 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Escaped_Html_Transformer;
56 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Html_V2_Transformer;
57 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Html_V3_Transformer;
58 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Link_Transformer;
59 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Plain_Transformer;
60 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Color_Overlay_Transformer;
61 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Gradient_Overlay_Transformer;
62 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Transformer;
63 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Color_Stop_Transformer;
64 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Multi_Props_Transformer;
65 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Position_Transformer;
66 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Shadow_Transformer;
67 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Grid_Track_Size_Transformer;
68 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Size_Transformer;
69 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Stroke_Transformer;
70 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Image_Overlay_Transformer;
71 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Image_Overlay_Size_Scale_Transformer;
72 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Overlay_Transformer;
73 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Filter_Transformer;
74 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Font_Family_Transformer;
75 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Origin_Transformer;
76 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transition_Transformer;
77 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Rotate_Transformer;
78 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Skew_Transformer;
79 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Functions_Transformer;
80 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Move_Transformer;
81 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Flex_Transformer;
82 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Scale_Transformer;
83 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Attributes_Transformer;
84 use Elementor\Modules\AtomicWidgets\PropTypes\Attributes_Prop_Type;
85 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers_Registry;
86 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Color_Overlay_Prop_Type;
87 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Gradient_Overlay_Prop_Type;
88 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Overlay_Size_Scale_Prop_Type;
89 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Overlay_Prop_Type;
90 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Position_Offset_Prop_Type;
91 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Overlay_Prop_Type;
92 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Prop_Type;
93 use Elementor\Modules\AtomicWidgets\PropTypes\Box_Shadow_Prop_Type;
94 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Radius_Prop_Type;
95 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Width_Prop_Type;
96 use Elementor\Modules\AtomicWidgets\PropTypes\Color_Stop_Prop_Type;
97 use Elementor\Modules\AtomicWidgets\PropTypes\Date_Time_Prop_Type;
98 use Elementor\Modules\AtomicWidgets\PropTypes\Date_Range_Prop_Type;
99 use Elementor\Modules\AtomicWidgets\PropTypes\Time_Range_Prop_Type;
100 use Elementor\Modules\AtomicWidgets\PropTypes\Filters\Backdrop_Filter_Prop_Type;
101 use Elementor\Modules\AtomicWidgets\PropTypes\Filters\Filter_Prop_Type;
102 use Elementor\Modules\AtomicWidgets\PropTypes\Gradient_Color_Stop_Prop_Type;
103 use Elementor\Modules\AtomicWidgets\PropTypes\Escaped_Html_Prop_Type;
104 use Elementor\Modules\AtomicWidgets\PropTypes\Html_V2_Prop_Type;
105 use Elementor\Modules\AtomicWidgets\PropTypes\Html_V3_Prop_Type;
106 use Elementor\Modules\AtomicWidgets\PropTypes\Layout_Direction_Prop_Type;
107 use Elementor\Modules\AtomicWidgets\PropTypes\Flex_Prop_Type;
108 use Elementor\Modules\AtomicWidgets\PropTypes\Link_Prop_Type;
109 use Elementor\Modules\AtomicWidgets\PropTypes\Classes_Prop_Type;
110 use Elementor\Modules\AtomicWidgets\PropTypes\Image_Prop_Type;
111 use Elementor\Modules\AtomicWidgets\PropTypes\Image_Src_Prop_Type;
112 use Elementor\Modules\AtomicWidgets\PropTypes\Icon_Prop_Type;
113 use Elementor\Modules\AtomicWidgets\PropTypes\Svg_Src_Prop_Type;
114 use Elementor\Modules\AtomicWidgets\PropTypes\Dimensions_Prop_Type;
115 use Elementor\Modules\AtomicWidgets\PropTypes\Position_Prop_Type;
116 use Elementor\Modules\AtomicWidgets\PropTypes\Shadow_Prop_Type;
117 use Elementor\Modules\AtomicWidgets\PropTypes\Grid_Track_Size_Prop_Type;
118 use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
119 use Elementor\Modules\AtomicWidgets\PropTypes\Stroke_Prop_Type;
120 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Move_Prop_Type;
121 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Functions_Prop_Type;
122 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Origin_Prop_Type;
123 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Scale_Prop_Type;
124 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Prop_Type;
125 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Rotate_Prop_Type;
126 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Skew_Prop_Type;
127 use Elementor\Modules\AtomicWidgets\PropTypes\Transition_Prop_Type;
128 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Styles_Manager;
129 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Widget_Base_Styles;
130 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Widget_Styles;
131 use Elementor\Modules\AtomicWidgets\Styles\Size_Constants;
132 use Elementor\Modules\AtomicWidgets\Styles\Style_Schema;
133 use Elementor\Modules\AtomicWidgets\CssConverter\Css_Converter_REST_API;
134 use Elementor\Modules\AtomicWidgets\Database\Atomic_Widgets_Database_Updater;
135 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video;
136 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Content\Atomic_Background_Video_Content;
137 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Controls\Atomic_Background_Video_Controls;
138 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Pause\Atomic_Background_Video_Pause;
139 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Play\Atomic_Background_Video_Play;
140 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tab_Content\Atomic_Tab_Content;
141 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Collection_Loop\Collection_Loop_Promotion;
142 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Atomic_Form;
143 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Atomic_Form_Promotion;
144 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Form_Success_Message\Form_Success_Message;
145 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Form_Error_Message\Form_Error_Message;
146 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List\Atomic_List;
147 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item\Atomic_List_Item;
148 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item_Content\Atomic_List_Item_Content;
149 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item_Marker\Atomic_List_Item_Marker;
150 use Elementor\Modules\AtomicWidgets\PropTypeMigrations\Migrations_Orchestrator;
151 use Elementor\Plugin;
152 use Elementor\Widgets_Manager;
153 use Elementor\Modules\AtomicWidgets\Library\Atomic_Widgets_Library;
154 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Query_Transformer;
155 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Date_Range_Transformer;
156 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Time_Range_Transformer;
157 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Perspective_Origin_Transformer;
158 use Elementor\Modules\AtomicWidgets\PropTypes\Query_Prop_Type;
159 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Perspective_Origin_Prop_Type;
160 use Elementor\Modules\AtomicWidgets\Utils\Atomic_Prop_Remap;
161 use Elementor\Modules\AtomicWidgets\Utils\Utils;
162 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Self_Hosted_Video\Atomic_Self_Hosted_Video;
163 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Span_Transformer;
164 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Video_Src_Transformer;
165 use Elementor\Modules\AtomicWidgets\PropTypes\Font_Family_Prop_Type;
166 use Elementor\Modules\AtomicWidgets\PropTypes\Span_Prop_Type;
167 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\Boolean_Prop_Type;
168 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\Number_Prop_Type;
169 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
170 use Elementor\Modules\AtomicWidgets\PropTypes\Video_Src_Prop_Type;
171
172 if ( ! defined( 'ABSPATH' ) ) {
173 exit; // Exit if accessed directly.
174 }
175
176 class Module extends BaseModule {
177 const EXPERIMENT_NAME = 'e_atomic_elements';
178 const EXPERIMENT_LIST = 'e_list';
179 const EXPERIMENT_ICON_BUTTON = 'e_icon_button';
180 const EXPERIMENT_ACCORDION = 'e_accordion';
181 const EXPERIMENT_ICON_LIBRARY = 'e_svg_library';
182
183 const PACKAGES = [
184 'editor-canvas',
185 'editor-controls',
186 'editor-editing-panel',
187 'editor-elements',
188 'editor-props',
189 'editor-styles',
190 'editor-styles-repository',
191 'editor-interactions',
192 'editor-templates',
193 'editor-design-system',
194 'editor-site-settings',
195 ];
196
197 public function get_name() {
198 return 'atomic-widgets';
199 }
200
201 public function __construct() {
202 parent::__construct();
203
204 if ( ! self::is_active() ) {
205 return;
206 }
207
208 $this->register_list_experiment();
209 $this->register_icon_button_experiment();
210 $this->register_accordion_experiment();
211 $this->register_icon_library_experiment();
212
213 $this->register_hooks();
214
215 add_filter( 'elementor/editor/v2/packages', fn ( $packages ) => $this->add_packages( $packages ) );
216 add_filter( 'elementor/editor/localize_settings', fn ( $settings ) => $this->add_styles_schema( $settings ) );
217 add_filter( 'elementor/editor/localize_settings', fn ( $settings ) => $this->add_supported_units( $settings ) );
218 add_filter( 'elementor/editor/localize_settings', fn ( $settings ) => $this->move_background_video_to_panel_end( $settings ) );
219 add_filter( 'elementor/widgets/register', fn ( Widgets_Manager $widgets_manager ) => $this->register_widgets( $widgets_manager ) );
220 add_filter( 'elementor/usage/elements/element_title', fn ( $title, $type ) => $this->get_element_usage_name( $title, $type ), 10, 2 );
221
222 add_action( 'elementor/elements/elements_registered', fn ( $elements_manager ) => $this->register_elements( $elements_manager ) );
223 add_action( 'elementor/editor/after_enqueue_scripts', fn () => $this->enqueue_scripts() );
224 add_action( 'elementor/editor/after_enqueue_styles', fn () => $this->enqueue_promotion_styles() );
225 add_action( 'elementor/preview/enqueue_styles', fn () => $this->enqueue_promotion_styles() );
226 add_action( 'elementor/frontend/before_register_scripts', fn () => $this->register_frontend_scripts() );
227 add_action( 'elementor/frontend/after_enqueue_styles', fn () => $this->add_inline_styles() );
228
229 add_action( 'elementor/ajax/register_actions', fn ( Ajax $ajax ) => ( new Render_Element_Action() )->register( $ajax ) );
230
231 add_action( 'elementor/atomic-widgets/settings/transformers/register', fn ( $transformers ) => $this->register_settings_transformers( $transformers ) );
232 add_action( 'elementor/atomic-widgets/styles/transformers/register', fn ( $transformers ) => $this->register_styles_transformers( $transformers ) );
233 add_action( 'elementor/atomic-widgets/import/transformers/register', fn ( $transformers ) => $this->register_import_transformers( $transformers ) );
234 add_action( 'elementor/atomic-widgets/export/transformers/register', fn ( $transformers ) => $this->register_export_transformers( $transformers ) );
235 add_action( 'elementor/atomic-widgets/plain/transformers/register', fn ( $transformers ) => $this->register_plain_transformers( $transformers ) );
236 add_action( 'elementor/atomic-widgets/settings-resolvers/register', fn ( $registry ) => $this->register_settings_resolvers( $registry ) );
237 add_action( 'elementor/editor/templates/panel/category', fn () => $this->render_panel_category_chip() );
238 }
239
240 public static function get_experimental_data() {
241 return [
242 'name' => self::EXPERIMENT_NAME,
243 'title' => esc_html__( 'Atomic Widgets', 'elementor' ),
244 'description' => esc_html__( 'Enable atomic widgets.', 'elementor' ),
245 'hidden' => true,
246 'default' => Experiments_Manager::STATE_INACTIVE,
247 'release_status' => Experiments_Manager::RELEASE_STATUS_BETA,
248 'new_site' => [
249 'default_active' => true,
250 'minimum_installation_version' => '4.0.0',
251 ],
252 ];
253 }
254
255 /**
256 * Dev-only gate that keeps the V4 List element off trunk while it is built across
257 * several pull requests. Remove it once the element passes QA.
258 */
259 private function register_list_experiment() {
260 Plugin::$instance->experiments->add_feature( [
261 'name' => self::EXPERIMENT_LIST,
262 'title' => esc_html__( 'List', 'elementor' ),
263 'description' => esc_html__( 'Enable the V4 List element.', 'elementor' ),
264 'hidden' => true,
265 'default' => Experiments_Manager::STATE_INACTIVE,
266 'release_status' => Experiments_Manager::RELEASE_STATUS_DEV,
267 ] );
268 }
269
270 /**
271 * Dev-only gate that keeps the V4 Icon Button element off trunk while it is built across
272 * several pull requests. Remove it once the element passes QA.
273 */
274 private function register_icon_button_experiment() {
275 Plugin::$instance->experiments->add_feature( [
276 'name' => self::EXPERIMENT_ICON_BUTTON,
277 'title' => esc_html__( 'Icon Button', 'elementor' ),
278 'description' => esc_html__( 'Enable the V4 Icon Button element.', 'elementor' ),
279 'hidden' => true,
280 'default' => Experiments_Manager::STATE_INACTIVE,
281 'release_status' => Experiments_Manager::RELEASE_STATUS_DEV,
282 ] );
283 }
284
285 private function register_accordion_experiment() {
286 Plugin::$instance->experiments->add_feature( [
287 'name' => self::EXPERIMENT_ACCORDION,
288 'title' => esc_html__( 'Accordion', 'elementor' ),
289 'description' => esc_html__( 'Enable the V4 Accordion element.', 'elementor' ),
290 'hidden' => true,
291 'default' => Experiments_Manager::STATE_INACTIVE,
292 'release_status' => Experiments_Manager::RELEASE_STATUS_DEV,
293 ] );
294 }
295
296 private function register_icon_library_experiment() {
297 Plugin::$instance->experiments->add_feature( [
298 'name' => self::EXPERIMENT_ICON_LIBRARY,
299 'title' => esc_html__( 'SVG Library', 'elementor' ),
300 'description' => esc_html__( 'Enable SVG library support in the SVG element.', 'elementor' ),
301 'hidden' => true,
302 'default' => Experiments_Manager::STATE_INACTIVE,
303 'release_status' => Experiments_Manager::RELEASE_STATUS_DEV,
304 ] );
305 }
306
307 private function register_hooks() {
308 Dynamic_Tags_Module::instance()->register_hooks();
309 Atomic_Styles_Manager::instance()->register_hooks();
310 Migrations_Orchestrator::make()->register_hooks();
311 ( new Atomic_Widget_Styles() )->register_hooks();
312 ( new Atomic_Widget_Base_Styles() )->register_hooks();
313 ( new Atomic_Widgets_Library() )->register_hooks();
314 ( new Atomic_Import_Export() )->register_hooks();
315 Atomic_Prop_Remap::register_builtin_handlers();
316 ( new Atomic_Widgets_Database_Updater() )->register();
317 ( new Css_Converter_REST_API() )->register_hooks();
318 ( new Pro_Promotion_Data_Preservation() )->register_hooks();
319
320 add_filter( 'elementor/allowed_html_wrapper_tags', [ $this, 'add_inline_html_tags' ] );
321 }
322
323 public function add_inline_html_tags( array $tags ): array {
324 return array_merge( $tags, [
325 'b',
326 'i',
327 'em',
328 'u',
329 'ul',
330 'ol',
331 'li',
332 'blockquote',
333 'del',
334 'br',
335 'span',
336 'strong',
337 'sup',
338 'sub',
339 's',
340 ] );
341 }
342
343 private function add_packages( $packages ) {
344 return array_merge( $packages, self::PACKAGES );
345 }
346
347 private function add_styles_schema( $settings ) {
348 if ( ! isset( $settings['atomic'] ) ) {
349 $settings['atomic'] = [];
350 }
351
352 $settings['atomic']['styles_schema'] = Style_Schema::get();
353
354 return $settings;
355 }
356
357 private function add_supported_units( $settings ) {
358 $settings['supported_size_units'] = Size_Constants::all_supported_units();
359
360 $settings['size_units'] = Size_Constants::grouped_units();
361
362 return $settings;
363 }
364
365 /**
366 * Background Video is a container element, so core lists it among the atomic *elements*, which
367 * always precede the atomic *widgets* in the widgets panel — `Document::get_config()` builds the
368 * panel list as `array_merge( $elements_config, $widget_types_config )`, and the panel renders
369 * tiles in that insertion order (there is no per-tile ordering field). The spec requires the tile
370 * at the very bottom of the Atomic Elements section, after Divider and Video (both widgets), so we
371 * re-append its config last in the initial document's widget list that seeds the editor cache.
372 */
373 private function move_background_video_to_panel_end( $settings ) {
374 $type = Atomic_Background_Video::get_element_type();
375
376 if ( empty( $settings['initial_document']['widgets'][ $type ] ) ) {
377 return $settings;
378 }
379
380 $widgets = $settings['initial_document']['widgets'];
381 $config = $widgets[ $type ];
382
383 unset( $widgets[ $type ] );
384 $widgets[ $type ] = $config;
385
386 $settings['initial_document']['widgets'] = $widgets;
387
388 return $settings;
389 }
390
391 private function register_widgets( Widgets_Manager $widgets_manager ) {
392 $widgets_manager->register( new Atomic_Heading() );
393 $widgets_manager->register( new Atomic_Image() );
394 $widgets_manager->register( new Atomic_Paragraph() );
395 $widgets_manager->register( new Atomic_Svg() );
396 $widgets_manager->register( new Atomic_Button() );
397 $widgets_manager->register( new Atomic_Youtube() );
398 $widgets_manager->register( new Atomic_Divider() );
399 $widgets_manager->register( new Atomic_Self_Hosted_Video() );
400 }
401
402 private function register_list_element( Elements_Manager $elements_manager ) {
403 if ( ! Plugin::$instance->experiments->is_feature_active( self::EXPERIMENT_LIST ) ) {
404 return $this;
405 }
406
407 $elements_manager->register_element_type( new Atomic_List() );
408 $elements_manager->register_element_type( new Atomic_List_Item() );
409 $elements_manager->register_element_type( new Atomic_List_Item_Marker() );
410 $elements_manager->register_element_type( new Atomic_List_Item_Content() );
411
412 return $this;
413 }
414
415 private function register_elements( Elements_Manager $elements_manager ) {
416 $elements_manager->register_element_type( new Div_Block() );
417 $elements_manager->register_element_type( new Flexbox() );
418 $elements_manager->register_element_type( new Grid() );
419
420 $elements_manager->register_element_type( new Atomic_Tabs() );
421 $elements_manager->register_element_type( new Atomic_Tabs_Menu() );
422 $elements_manager->register_element_type( new Atomic_Tab() );
423 $elements_manager->register_element_type( new Atomic_Tabs_Content_Area() );
424 $elements_manager->register_element_type( new Atomic_Tab_Content() );
425
426 $this->register_list_element( $elements_manager );
427
428 $elements_manager->register_element_type( new Atomic_Accordion() );
429 $elements_manager->register_element_type( new Atomic_Accordion_Item() );
430 $elements_manager->register_element_type( new Atomic_Accordion_Item_Header() );
431 $elements_manager->register_element_type( new Atomic_Accordion_Item_Title() );
432 $elements_manager->register_element_type( new Atomic_Accordion_Item_Icon() );
433 $elements_manager->register_element_type( new Atomic_Accordion_Item_Content() );
434
435 $elements_manager->register_element_type( new Atomic_Background_Video() );
436 $elements_manager->register_element_type( new Atomic_Background_Video_Content() );
437 $elements_manager->register_element_type( new Atomic_Background_Video_Controls() );
438 $elements_manager->register_element_type( new Atomic_Background_Video_Play() );
439 $elements_manager->register_element_type( new Atomic_Background_Video_Pause() );
440
441 if ( \Elementor\Utils::has_pro() && Plugin::$instance->experiments->is_feature_active( 'e_pro_atomic_form' ) ) {
442 $elements_manager->register_element_type( new Atomic_Form() );
443 $elements_manager->register_element_type( new Form_Success_Message() );
444 $elements_manager->register_element_type( new Form_Error_Message() );
445 } elseif ( ! \Elementor\Utils::has_pro() ) {
446 $elements_manager->register_element_type( new Atomic_Form_Promotion() );
447 }
448
449 if ( ! \Elementor\Utils::has_pro() ) {
450 $elements_manager->register_element_type( new Collection_Loop_Promotion() );
451 }
452 }
453
454 private function register_settings_transformers( Transformers_Registry $transformers ) {
455 $transformers->register_fallback( new Plain_Transformer() );
456 $transformers->register( Classes_Prop_Type::get_key(), new Classes_Transformer() );
457 $transformers->register( Image_Prop_Type::get_key(), new Image_Transformer() );
458 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Transformer() );
459 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Transformer() );
460 $transformers->register( Icon_Prop_Type::get_key(), new Icon_Transformer() );
461 $transformers->register( Video_Src_Prop_Type::get_key(), new Video_Src_Transformer() );
462 $transformers->register( Link_Prop_Type::get_key(), new Link_Transformer() );
463 $transformers->register( Query_Prop_Type::get_key(), new Query_Transformer() );
464 $transformers->register( Attributes_Prop_Type::get_key(), new Attributes_Transformer() );
465 $transformers->register( Date_Time_Prop_Type::get_key(), new Date_Time_Transformer() );
466 $transformers->register( Date_Range_Prop_Type::get_key(), new Date_Range_Transformer() );
467 $transformers->register( Time_Range_Prop_Type::get_key(), new Time_Range_Transformer() );
468 $transformers->register( Html_V2_Prop_Type::get_key(), new Html_V2_Transformer() );
469 $transformers->register( Html_V3_Prop_Type::get_key(), new Html_V3_Transformer() );
470 $transformers->register( Escaped_Html_Prop_Type::get_key(), new Escaped_Html_Transformer() );
471 }
472
473 private function register_styles_transformers( Transformers_Registry $transformers ) {
474 $transformers->register_fallback( new Plain_Transformer() );
475
476 $this->register_basic_styles_transformers( $transformers );
477 $this->register_background_styles_transformers( $transformers );
478 $this->register_filter_styles_transformers( $transformers );
479 $this->register_transform_styles_transformers( $transformers );
480 $this->register_layout_styles_transformers( $transformers );
481 }
482
483 private function register_basic_styles_transformers( Transformers_Registry $transformers ): void {
484 $transformers->register( Font_Family_Prop_Type::get_key(), new Font_Family_Transformer() );
485 $transformers->register( Size_Prop_Type::get_key(), new Size_Transformer() );
486 $transformers->register( Grid_Track_Size_Prop_Type::get_key(), new Grid_Track_Size_Transformer() );
487 $transformers->register( Box_Shadow_Prop_Type::get_key(), new Combine_Array_Transformer( ',' ) );
488 $transformers->register( Shadow_Prop_Type::get_key(), new Shadow_Transformer() );
489 $transformers->register( Flex_Prop_Type::get_key(), new Flex_Transformer() );
490 $transformers->register( Stroke_Prop_Type::get_key(), new Stroke_Transformer() );
491 $transformers->register( Image_Prop_Type::get_key(), new Image_Transformer() );
492 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Transformer() );
493 $transformers->register( Span_Prop_Type::get_key(), new Span_Transformer() );
494 }
495
496 private function register_background_styles_transformers( Transformers_Registry $transformers ): void {
497 $transformers->register( Background_Image_Overlay_Prop_Type::get_key(), new Background_Image_Overlay_Transformer() );
498 $transformers->register( Background_Image_Overlay_Size_Scale_Prop_Type::get_key(), new Background_Image_Overlay_Size_Scale_Transformer() );
499 $transformers->register( Background_Image_Position_Offset_Prop_Type::get_key(), new Position_Transformer() );
500 $transformers->register( Background_Color_Overlay_Prop_Type::get_key(), new Background_Color_Overlay_Transformer() );
501 $transformers->register( Background_Overlay_Prop_Type::get_key(), new Background_Overlay_Transformer() );
502 $transformers->register( Background_Prop_Type::get_key(), new Background_Transformer() );
503 $transformers->register( Background_Gradient_Overlay_Prop_Type::get_key(), new Background_Gradient_Overlay_Transformer() );
504 }
505
506 private function register_filter_styles_transformers( Transformers_Registry $transformers ): void {
507 $transformers->register( Filter_Prop_Type::get_key(), new Filter_Transformer() );
508 $transformers->register( Backdrop_Filter_Prop_Type::get_key(), new Filter_Transformer() );
509 $transformers->register( Transition_Prop_Type::get_key(), new Transition_Transformer() );
510 $transformers->register( Color_Stop_Prop_Type::get_key(), new Color_Stop_Transformer() );
511 $transformers->register( Gradient_Color_Stop_Prop_Type::get_key(), new Combine_Array_Transformer( ',' ) );
512 $transformers->register( Position_Prop_Type::get_key(), new Position_Transformer() );
513 }
514
515 private function register_transform_styles_transformers( Transformers_Registry $transformers ): void {
516 $transformers->register( Transform_Move_Prop_Type::get_key(), new Transform_Move_Transformer() );
517 $transformers->register( Transform_Scale_Prop_Type::get_key(), new Transform_Scale_Transformer() );
518 $transformers->register( Transform_Rotate_Prop_Type::get_key(), new Transform_Rotate_Transformer() );
519 $transformers->register( Transform_Skew_Prop_Type::get_key(), new Transform_Skew_Transformer() );
520 $transformers->register( Transform_Functions_Prop_Type::get_key(), new Transform_Functions_Transformer() );
521 $transformers->register( Transform_Origin_Prop_Type::get_key(), new Transform_Origin_Transformer() );
522 $transformers->register( Perspective_Origin_Prop_Type::get_key(), new Perspective_Origin_Transformer() );
523 $transformers->register(
524 Transform_Prop_Type::get_key(),
525 new Multi_Props_Transformer(
526 [ 'transform-functions', 'transform-origin', 'perspective', 'perspective-origin' ],
527 fn( $_, $key ) => 'transform-functions' === $key ? 'transform' : $key
528 )
529 );
530 }
531
532 private function register_layout_styles_transformers( Transformers_Registry $transformers ): void {
533 $transformers->register(
534 Border_Radius_Prop_Type::get_key(),
535 new Multi_Props_Transformer( [ 'start-start', 'start-end', 'end-start', 'end-end' ], fn ( $_, $key ) => "border-{$key}-radius" )
536 );
537 $transformers->register(
538 Border_Width_Prop_Type::get_key(),
539 new Multi_Props_Transformer( [ 'block-start', 'block-end', 'inline-start', 'inline-end' ], fn ( $_, $key ) => "border-{$key}-width" )
540 );
541 $transformers->register(
542 Layout_Direction_Prop_Type::get_key(),
543 new Multi_Props_Transformer( [ 'column', 'row' ], fn ( $prop_key, $key ) => "{$key}-{$prop_key}" )
544 );
545 $transformers->register(
546 Dimensions_Prop_Type::get_key(),
547 new Multi_Props_Transformer( [ 'block-start', 'block-end', 'inline-start', 'inline-end' ], fn ( $prop_key, $key ) => "{$prop_key}-{$key}" )
548 );
549 }
550
551 public function register_import_transformers( Transformers_Registry $transformers ) {
552 $transformers->register_fallback( new Import_Export_Plain_Transformer() );
553
554 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Import_Transformer() );
555 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Import_Transformer() );
556 }
557
558 public function register_export_transformers( Transformers_Registry $transformers ) {
559 $transformers->register_fallback( new Import_Export_Plain_Transformer() );
560
561 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Export_Transformer() );
562 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Export_Transformer() );
563 }
564
565 public function register_plain_transformers( Transformers_Registry $transformers ) {
566 $transformers->register_fallback( new Plain_Transformer() );
567 }
568
569 private function register_settings_resolvers( Plain_Resolvers_Registry $registry ): void {
570 $registry->register_fallback( new Passthrough_Plain_Resolver() );
571 $registry->register( Number_Prop_Type::get_key(), new Number_Plain_Resolver() );
572 $registry->register( Boolean_Prop_Type::get_key(), new Boolean_Plain_Resolver() );
573 $registry->register( String_Prop_Type::get_key(), new String_Plain_Resolver() );
574 $registry->register( Size_Prop_Type::get_key(), new Size_Plain_Resolver() );
575 }
576
577 public function get_settings_plain_values_resolver(): Plain_Values_Resolver {
578 static $resolver = null;
579
580 if ( null !== $resolver ) {
581 return $resolver;
582 }
583
584 $registry = new Plain_Resolvers_Registry();
585
586 do_action( 'elementor/atomic-widgets/settings-resolvers/register', $registry );
587
588 $resolver = new Plain_Values_Resolver( $registry );
589
590 $registry->register( Dynamic_Prop_Type::get_key(), new Dynamic_Plain_Resolver( $resolver ) );
591 $registry->register( Escaped_Html_Prop_Type::get_key(), new String_Plain_Resolver() );
592
593 return $resolver;
594 }
595
596 public static function is_active(): bool {
597 return Plugin::$instance->experiments->is_feature_active( self::EXPERIMENT_NAME );
598 }
599
600 public static function is_svg_library_active(): bool {
601 return Plugin::$instance->experiments->is_feature_active( self::EXPERIMENT_ICON_LIBRARY );
602 }
603
604 private function get_element_usage_name( $title, $type ) {
605 $element_instance = Plugin::$instance->elements_manager->get_element_types( $type );
606 $widget_instance = Plugin::$instance->widgets_manager->get_widget_types( $type );
607
608 if ( Utils::is_atomic( $element_instance ) || Utils::is_atomic( $widget_instance ) ) {
609 return $type;
610 }
611
612 return $title;
613 }
614
615 /**
616 * Enqueue the module scripts.
617 *
618 * @return void
619 */
620 private function enqueue_scripts() {
621 wp_enqueue_script(
622 'elementor-atomic-widgets-editor',
623 $this->get_js_assets_url( 'atomic-widgets-editor' ),
624 [ 'elementor-editor' ],
625 ELEMENTOR_VERSION,
626 true
627 );
628
629 wp_set_script_translations( 'elementor-atomic-widgets-editor', 'elementor' );
630 }
631
632 private function render_panel_category_chip() {
633 ?><# if ( 'v4-elements' === name ) { #>
634 <span class="elementor-panel-heading-category-chip" aria-label="<?php echo esc_attr__( 'New', 'elementor' ); ?>">
635 <i class="eicon-info" aria-hidden="true"></i>
636 <span class="e-promotion-react-wrapper" data-promotion="v4_chip"></span>
637 </span>
638 <# } #><?php
639 }
640
641 private function register_frontend_scripts() {
642 $loader = new Frontend_Assets_Loader();
643 $loader->register_scripts();
644 }
645
646 private function add_inline_styles() {
647 $inline_css = implode( '', [
648 '.e-heading-base a, .e-paragraph-base a { all: unset; cursor: pointer; }',
649 'form[data-element_type="e-form"].form-state-success [data-element_type="e-form-success-message"],',
650 'form[data-element_type="e-form"].form-state-error [data-element_type="e-form-error-message"]',
651 '{ display: block; }',
652 // Base style is `display: none`. In the editor, still show the slot when it is
653 // selected (navigator / canvas), when a nested child is selected, or when empty
654 // so the plus/drop target has a hit area. Frontend and unselected Normal stay hidden.
655 '.elementor-edit-mode [data-element_type="e-form-success-message"]:is(.elementor-element-editable, :has(.elementor-element-editable), :has(> .elementor-empty-view)),',
656 '.elementor-edit-mode [data-element_type="e-form-error-message"]:is(.elementor-element-editable, :has(.elementor-element-editable), :has(> .elementor-empty-view))',
657 '{ display: block; }',
658 '.e-background-video { position: relative; overflow: hidden; }',
659 '.e-background-video__media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; z-index: 0; }',
660 '.e-background-video__content { position: relative; z-index: 1; flex: 1 1 auto; }',
661 // Editor empty state: content is a nested flex child inside padded root (overflow:hidden).
662 // Let content shrink to the inner flex area, then grow the empty-view to fill it.
663 '.elementor-edit-mode .e-background-video__content.e-atomic-element:has(> .elementor-empty-view) { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }',
664 '.elementor-edit-mode .e-background-video__content.e-atomic-element:has(> .elementor-empty-view) > .elementor-empty-view.elementor-empty-view { position: relative; flex: 1 1 auto; min-height: 120px; height: auto; width: 100%; }',
665 '.elementor-edit-mode .e-background-video__content.e-atomic-element:has(> .elementor-empty-view) > .elementor-empty-view > .elementor-first-add { position: absolute; inset: 0; width: 100%; height: 100%; }',
666 '.e-background-video__controls { z-index: 2; }',
667 '.e-background-video__play, .e-background-video__pause { appearance: none; -webkit-appearance: none; }',
668 '.e-background-video.e-background-video--playing .e-background-video__play { display: none; }',
669 '.e-background-video.e-background-video--paused .e-background-video__pause { display: none; }',
670 // No state pinned (editor "States" unselected): hide the controls wrapper and both buttons. The
671 // two `:not` guards lift specificity above the atomic base style so `display: none` wins. The
672 // button rules are kept because the buttons can be reparented out of the wrapper. On the
673 // frontend Alpine always sets one of the state classes from real playback, so the controls show
674 // there with exactly one button.
675 '.e-background-video:not(.e-background-video--playing):not(.e-background-video--paused) .e-background-video__controls,',
676 '.e-background-video:not(.e-background-video--playing):not(.e-background-video--paused) .e-background-video__play,',
677 '.e-background-video:not(.e-background-video--playing):not(.e-background-video--paused) .e-background-video__pause { display: none; }',
678 // Accordion: `<summary>` already loses its native marker via `display: flex` on the header's
679 // base style in Chrome/Firefox, but Safari renders `::-webkit-details-marker` regardless of
680 // `display`, so a stray triangle would sit next to our chevron unless the pseudo-element is
681 // killed explicitly. `list-style: none` is kept for completeness (browsers that box the
682 // marker as a list-item marker box), the `::-webkit-details-marker` rule is what actually
683 // fixes Safari.
684 '.e-accordion-item-header-base { list-style: none; }',
685 '.e-accordion-item-header-base::-webkit-details-marker { display: none; }',
686 // Animated expand/collapse via `::details-content` (block-size 0 -> auto) needs
687 // `interpolate-size: allow-keywords` on the <details> element to let `block-size: auto`
688 // participate in the transition. Graceful degradation is deliberate here, but the two failure
689 // modes are different: `interpolate-size` is a real CSS property with a valid selector
690 // (`.e-accordion-item-base`), so that rule always PARSES everywhere — an unsupporting browser
691 // just drops the one unknown *declaration* inside it (inert on its own; harmless). The two
692 // `::details-content` rules are different: `::details-content` is an unrecognised
693 // pseudo-element there, which invalidates the *whole selector*, so the *entire rule* is
694 // dropped, not just a declaration. That whole-rule drop is what structurally guarantees
695 // "collapse to 0" and "expand on [open]" can never apply one without the other — both live
696 // behind the identical `::details-content` requirement, so an unsupporting browser parses
697 // neither and simply keeps the browser's native <details> toggle (content already shown/hidden
698 // correctly without any CSS from us): an instant toggle, never a silently blanked panel.
699 '.e-accordion-item-base { interpolate-size: allow-keywords; }',
700 '.e-accordion-item-base::details-content {',
701 'block-size: 0; overflow: hidden;',
702 'transition: block-size .3s ease, content-visibility .3s ease allow-discrete;',
703 '}',
704 '.e-accordion-item-base[open]::details-content { block-size: auto; }',
705 // Accordion icon slot: see docs/accordion_v4_icon_slot_behaviors.md
706 '.e-accordion-item-icon-base.e-accordion-item-icon-base .e-svg-base { width: auto; height: 100%; max-width: 100%; }',
707 '.e-accordion-item-icon-base.e-accordion-item-icon-base .e-svg-base svg { width: auto !important; }',
708 '.e-accordion-item-icon-base svg { transition: transform .3s ease; }',
709 '.e-accordion-item-base[open] > summary .e-accordion-item-icon-base svg { transform: rotate(180deg); }',
710 ] );
711 wp_add_inline_style( 'elementor-frontend', $inline_css );
712 wp_add_inline_style( 'elementor-editor', $inline_css );
713 }
714
715 private function enqueue_promotion_styles() {
716 if ( \Elementor\Utils::has_pro() ) {
717 return;
718 }
719
720 wp_enqueue_style(
721 'elementor-atomic-widgets-promotion-fonts',
722 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap',
723 [],
724 ELEMENTOR_VERSION
725 );
726
727 wp_enqueue_style(
728 'elementor-atomic-widgets-promotion',
729 $this->get_css_assets_url( 'modules/atomic-widgets/editor' ),
730 [ 'elementor-atomic-widgets-promotion-fonts' ],
731 ELEMENTOR_VERSION
732 );
733 }
734 }
735