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

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

726 lines 40.2 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\Html_V3_Plain_Resolver;
17 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Passthrough_Plain_Resolver;
18 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Number_Plain_Resolver;
19 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\Size_Plain_Resolver;
20 use Elementor\Modules\AtomicWidgets\PlainResolvers\Resolvers\String_Plain_Resolver;
21 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Youtube\Atomic_Youtube;
22 use Elementor\Modules\AtomicWidgets\Elements\Div_Block\Div_Block;
23 use Elementor\Modules\AtomicWidgets\Elements\Flexbox\Flexbox;
24 use Elementor\Modules\AtomicWidgets\Elements\Grid\Grid;
25 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Heading\Atomic_Heading;
26 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Image\Atomic_Image;
27 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Paragraph\Atomic_Paragraph;
28 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Button\Atomic_Button;
29 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Divider\Atomic_Divider;
30 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Svg\Atomic_Svg;
31 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion;
32 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item\Atomic_Accordion_Item;
33 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Content\Atomic_Accordion_Item_Content;
34 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Header\Atomic_Accordion_Item_Header;
35 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Icon\Atomic_Accordion_Item_Icon;
36 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Accordion\Atomic_Accordion_Item_Title\Atomic_Accordion_Item_Title;
37 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs\Atomic_Tabs;
38 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs_Menu\Atomic_Tabs_Menu;
39 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tab\Atomic_Tab;
40 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tabs_Content_Area\Atomic_Tabs_Content_Area;
41 use Elementor\Modules\AtomicWidgets\ImportExport\Atomic_Import_Export;
42 use Elementor\Modules\AtomicWidgets\Elements\Promotions\Pro_Promotion_Data_Preservation;
43 use Elementor\Modules\AtomicWidgets\Elements\Loader\Frontend_Assets_Loader;
44 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Combine_Array_Transformer;
45 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Export\Image_Src_Export_Transformer;
46 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Export\Svg_Src_Export_Transformer;
47 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Image_Src_Transformer;
48 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Image_Transformer;
49 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import\Image_Src_Import_Transformer;
50 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import\Svg_Src_Import_Transformer;
51 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Icon_Transformer;
52 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Svg_Src_Transformer;
53 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Import_Export_Plain_Transformer;
54 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Classes_Transformer;
55 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Date_Time_Transformer;
56 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Escaped_Html_Transformer;
57 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Html_V2_Transformer;
58 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Html_V3_Transformer;
59 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Link_Transformer;
60 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Plain_Transformer;
61 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Color_Overlay_Transformer;
62 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Gradient_Overlay_Transformer;
63 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Transformer;
64 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Color_Stop_Transformer;
65 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Multi_Props_Transformer;
66 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Position_Transformer;
67 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Shadow_Transformer;
68 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Grid_Track_Size_Transformer;
69 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Size_Transformer;
70 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Stroke_Transformer;
71 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Image_Overlay_Transformer;
72 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Image_Overlay_Size_Scale_Transformer;
73 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Background_Overlay_Transformer;
74 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Filter_Transformer;
75 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Font_Family_Transformer;
76 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Origin_Transformer;
77 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transition_Transformer;
78 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Rotate_Transformer;
79 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Skew_Transformer;
80 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Functions_Transformer;
81 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Move_Transformer;
82 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Flex_Transformer;
83 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Transform_Scale_Transformer;
84 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Attributes_Transformer;
85 use Elementor\Modules\AtomicWidgets\PropTypes\Attributes_Prop_Type;
86 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers_Registry;
87 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Color_Overlay_Prop_Type;
88 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Gradient_Overlay_Prop_Type;
89 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Overlay_Size_Scale_Prop_Type;
90 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Overlay_Prop_Type;
91 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Position_Offset_Prop_Type;
92 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Overlay_Prop_Type;
93 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Prop_Type;
94 use Elementor\Modules\AtomicWidgets\PropTypes\Box_Shadow_Prop_Type;
95 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Radius_Prop_Type;
96 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Width_Prop_Type;
97 use Elementor\Modules\AtomicWidgets\PropTypes\Color_Stop_Prop_Type;
98 use Elementor\Modules\AtomicWidgets\PropTypes\Date_Time_Prop_Type;
99 use Elementor\Modules\AtomicWidgets\PropTypes\Date_Range_Prop_Type;
100 use Elementor\Modules\AtomicWidgets\PropTypes\Time_Range_Prop_Type;
101 use Elementor\Modules\AtomicWidgets\PropTypes\Filters\Backdrop_Filter_Prop_Type;
102 use Elementor\Modules\AtomicWidgets\PropTypes\Filters\Filter_Prop_Type;
103 use Elementor\Modules\AtomicWidgets\PropTypes\Gradient_Color_Stop_Prop_Type;
104 use Elementor\Modules\AtomicWidgets\PropTypes\Escaped_Html_Prop_Type;
105 use Elementor\Modules\AtomicWidgets\PropTypes\Html_V2_Prop_Type;
106 use Elementor\Modules\AtomicWidgets\PropTypes\Html_V3_Prop_Type;
107 use Elementor\Modules\AtomicWidgets\PropTypes\Layout_Direction_Prop_Type;
108 use Elementor\Modules\AtomicWidgets\PropTypes\Flex_Prop_Type;
109 use Elementor\Modules\AtomicWidgets\PropTypes\Link_Prop_Type;
110 use Elementor\Modules\AtomicWidgets\PropTypes\Classes_Prop_Type;
111 use Elementor\Modules\AtomicWidgets\PropTypes\Image_Prop_Type;
112 use Elementor\Modules\AtomicWidgets\PropTypes\Image_Src_Prop_Type;
113 use Elementor\Modules\AtomicWidgets\PropTypes\Icon_Prop_Type;
114 use Elementor\Modules\AtomicWidgets\PropTypes\Svg_Src_Prop_Type;
115 use Elementor\Modules\AtomicWidgets\PropTypes\Dimensions_Prop_Type;
116 use Elementor\Modules\AtomicWidgets\PropTypes\Position_Prop_Type;
117 use Elementor\Modules\AtomicWidgets\PropTypes\Shadow_Prop_Type;
118 use Elementor\Modules\AtomicWidgets\PropTypes\Grid_Track_Size_Prop_Type;
119 use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
120 use Elementor\Modules\AtomicWidgets\PropTypes\Stroke_Prop_Type;
121 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Move_Prop_Type;
122 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Functions_Prop_Type;
123 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Origin_Prop_Type;
124 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Scale_Prop_Type;
125 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Transform_Prop_Type;
126 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Rotate_Prop_Type;
127 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Functions\Transform_Skew_Prop_Type;
128 use Elementor\Modules\AtomicWidgets\PropTypes\Transition_Prop_Type;
129 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Styles_Manager;
130 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Widget_Base_Styles;
131 use Elementor\Modules\AtomicWidgets\Styles\Atomic_Widget_Styles;
132 use Elementor\Modules\AtomicWidgets\Styles\Size_Constants;
133 use Elementor\Modules\AtomicWidgets\Styles\Style_Schema;
134 use Elementor\Modules\AtomicWidgets\CssConverter\Css_Converter_REST_API;
135 use Elementor\Modules\AtomicWidgets\Database\Atomic_Widgets_Database_Updater;
136 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video;
137 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Content\Atomic_Background_Video_Content;
138 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Controls\Atomic_Background_Video_Controls;
139 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Pause\Atomic_Background_Video_Pause;
140 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Background_Video\Atomic_Background_Video_Play\Atomic_Background_Video_Play;
141 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Tabs\Atomic_Tab_Content\Atomic_Tab_Content;
142 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Collection_Loop\Collection_Loop_Promotion;
143 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Atomic_Form;
144 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Atomic_Form_Promotion;
145 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Form_Success_Message\Form_Success_Message;
146 use Elementor\Modules\AtomicWidgets\Elements\Atomic_Form\Form_Error_Message\Form_Error_Message;
147 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List\Atomic_List;
148 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item\Atomic_List_Item;
149 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item_Content\Atomic_List_Item_Content;
150 use Elementor\Modules\AtomicWidgets\Elements\Atomic_List\Atomic_List_Item_Marker\Atomic_List_Item_Marker;
151 use Elementor\Modules\AtomicWidgets\PropTypeMigrations\Migrations_Orchestrator;
152 use Elementor\Plugin;
153 use Elementor\Widgets_Manager;
154 use Elementor\Modules\AtomicWidgets\Library\Atomic_Widgets_Library;
155 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Query_Transformer;
156 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Date_Range_Transformer;
157 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Time_Range_Transformer;
158 use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Styles\Perspective_Origin_Transformer;
159 use Elementor\Modules\AtomicWidgets\PropTypes\Query_Prop_Type;
160 use Elementor\Modules\AtomicWidgets\PropTypes\Transform\Perspective_Origin_Prop_Type;
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 ( new Atomic_Widgets_Database_Updater() )->register();
316 ( new Css_Converter_REST_API() )->register_hooks();
317 ( new Pro_Promotion_Data_Preservation() )->register_hooks();
318
319 add_filter( 'elementor/allowed_html_wrapper_tags', [ $this, 'add_inline_html_tags' ] );
320 }
321
322 public function add_inline_html_tags( array $tags ): array {
323 return array_merge( $tags, [
324 'b',
325 'i',
326 'em',
327 'u',
328 'ul',
329 'ol',
330 'li',
331 'blockquote',
332 'del',
333 'br',
334 'span',
335 'strong',
336 'sup',
337 'sub',
338 's',
339 ] );
340 }
341
342 private function add_packages( $packages ) {
343 return array_merge( $packages, self::PACKAGES );
344 }
345
346 private function add_styles_schema( $settings ) {
347 if ( ! isset( $settings['atomic'] ) ) {
348 $settings['atomic'] = [];
349 }
350
351 $settings['atomic']['styles_schema'] = Style_Schema::get();
352
353 return $settings;
354 }
355
356 private function add_supported_units( $settings ) {
357 $settings['supported_size_units'] = Size_Constants::all_supported_units();
358
359 $settings['size_units'] = Size_Constants::grouped_units();
360
361 return $settings;
362 }
363
364 /**
365 * Background Video is a container element, so core lists it among the atomic *elements*, which
366 * always precede the atomic *widgets* in the widgets panel — `Document::get_config()` builds the
367 * panel list as `array_merge( $elements_config, $widget_types_config )`, and the panel renders
368 * tiles in that insertion order (there is no per-tile ordering field). The spec requires the tile
369 * at the very bottom of the Atomic Elements section, after Divider and Video (both widgets), so we
370 * re-append its config last in the initial document's widget list that seeds the editor cache.
371 */
372 private function move_background_video_to_panel_end( $settings ) {
373 $type = Atomic_Background_Video::get_element_type();
374
375 if ( empty( $settings['initial_document']['widgets'][ $type ] ) ) {
376 return $settings;
377 }
378
379 $widgets = $settings['initial_document']['widgets'];
380 $config = $widgets[ $type ];
381
382 unset( $widgets[ $type ] );
383 $widgets[ $type ] = $config;
384
385 $settings['initial_document']['widgets'] = $widgets;
386
387 return $settings;
388 }
389
390 private function register_widgets( Widgets_Manager $widgets_manager ) {
391 $widgets_manager->register( new Atomic_Heading() );
392 $widgets_manager->register( new Atomic_Image() );
393 $widgets_manager->register( new Atomic_Paragraph() );
394 $widgets_manager->register( new Atomic_Svg() );
395 $widgets_manager->register( new Atomic_Button() );
396 $widgets_manager->register( new Atomic_Youtube() );
397 $widgets_manager->register( new Atomic_Divider() );
398 $widgets_manager->register( new Atomic_Self_Hosted_Video() );
399 }
400
401 private function register_list_element( Elements_Manager $elements_manager ) {
402 if ( ! Plugin::$instance->experiments->is_feature_active( self::EXPERIMENT_LIST ) ) {
403 return $this;
404 }
405
406 $elements_manager->register_element_type( new Atomic_List() );
407 $elements_manager->register_element_type( new Atomic_List_Item() );
408 $elements_manager->register_element_type( new Atomic_List_Item_Marker() );
409 $elements_manager->register_element_type( new Atomic_List_Item_Content() );
410
411 return $this;
412 }
413
414 private function register_elements( Elements_Manager $elements_manager ) {
415 $elements_manager->register_element_type( new Div_Block() );
416 $elements_manager->register_element_type( new Flexbox() );
417 $elements_manager->register_element_type( new Grid() );
418
419 $elements_manager->register_element_type( new Atomic_Tabs() );
420 $elements_manager->register_element_type( new Atomic_Tabs_Menu() );
421 $elements_manager->register_element_type( new Atomic_Tab() );
422 $elements_manager->register_element_type( new Atomic_Tabs_Content_Area() );
423 $elements_manager->register_element_type( new Atomic_Tab_Content() );
424
425 $this->register_list_element( $elements_manager );
426
427 $elements_manager->register_element_type( new Atomic_Accordion() );
428 $elements_manager->register_element_type( new Atomic_Accordion_Item() );
429 $elements_manager->register_element_type( new Atomic_Accordion_Item_Header() );
430 $elements_manager->register_element_type( new Atomic_Accordion_Item_Title() );
431 $elements_manager->register_element_type( new Atomic_Accordion_Item_Icon() );
432 $elements_manager->register_element_type( new Atomic_Accordion_Item_Content() );
433
434 $elements_manager->register_element_type( new Atomic_Background_Video() );
435 $elements_manager->register_element_type( new Atomic_Background_Video_Content() );
436 $elements_manager->register_element_type( new Atomic_Background_Video_Controls() );
437 $elements_manager->register_element_type( new Atomic_Background_Video_Play() );
438 $elements_manager->register_element_type( new Atomic_Background_Video_Pause() );
439
440 if ( \Elementor\Utils::has_pro() && Plugin::$instance->experiments->is_feature_active( 'e_pro_atomic_form' ) ) {
441 $elements_manager->register_element_type( new Atomic_Form() );
442 $elements_manager->register_element_type( new Form_Success_Message() );
443 $elements_manager->register_element_type( new Form_Error_Message() );
444 } elseif ( ! \Elementor\Utils::has_pro() ) {
445 $elements_manager->register_element_type( new Atomic_Form_Promotion() );
446 }
447
448 if ( ! \Elementor\Utils::has_pro() ) {
449 $elements_manager->register_element_type( new Collection_Loop_Promotion() );
450 }
451 }
452
453 private function register_settings_transformers( Transformers_Registry $transformers ) {
454 $transformers->register_fallback( new Plain_Transformer() );
455 $transformers->register( Classes_Prop_Type::get_key(), new Classes_Transformer() );
456 $transformers->register( Image_Prop_Type::get_key(), new Image_Transformer() );
457 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Transformer() );
458 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Transformer() );
459 $transformers->register( Icon_Prop_Type::get_key(), new Icon_Transformer() );
460 $transformers->register( Video_Src_Prop_Type::get_key(), new Video_Src_Transformer() );
461 $transformers->register( Link_Prop_Type::get_key(), new Link_Transformer() );
462 $transformers->register( Query_Prop_Type::get_key(), new Query_Transformer() );
463 $transformers->register( Attributes_Prop_Type::get_key(), new Attributes_Transformer() );
464 $transformers->register( Date_Time_Prop_Type::get_key(), new Date_Time_Transformer() );
465 $transformers->register( Date_Range_Prop_Type::get_key(), new Date_Range_Transformer() );
466 $transformers->register( Time_Range_Prop_Type::get_key(), new Time_Range_Transformer() );
467 $transformers->register( Html_V2_Prop_Type::get_key(), new Html_V2_Transformer() );
468 $transformers->register( Html_V3_Prop_Type::get_key(), new Html_V3_Transformer() );
469 $transformers->register( Escaped_Html_Prop_Type::get_key(), new Escaped_Html_Transformer() );
470 }
471
472 private function register_styles_transformers( Transformers_Registry $transformers ) {
473 $transformers->register_fallback( new Plain_Transformer() );
474
475 $this->register_basic_styles_transformers( $transformers );
476 $this->register_background_styles_transformers( $transformers );
477 $this->register_filter_styles_transformers( $transformers );
478 $this->register_transform_styles_transformers( $transformers );
479 $this->register_layout_styles_transformers( $transformers );
480 }
481
482 private function register_basic_styles_transformers( Transformers_Registry $transformers ): void {
483 $transformers->register( Font_Family_Prop_Type::get_key(), new Font_Family_Transformer() );
484 $transformers->register( Size_Prop_Type::get_key(), new Size_Transformer() );
485 $transformers->register( Grid_Track_Size_Prop_Type::get_key(), new Grid_Track_Size_Transformer() );
486 $transformers->register( Box_Shadow_Prop_Type::get_key(), new Combine_Array_Transformer( ',' ) );
487 $transformers->register( Shadow_Prop_Type::get_key(), new Shadow_Transformer() );
488 $transformers->register( Flex_Prop_Type::get_key(), new Flex_Transformer() );
489 $transformers->register( Stroke_Prop_Type::get_key(), new Stroke_Transformer() );
490 $transformers->register( Image_Prop_Type::get_key(), new Image_Transformer() );
491 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Transformer() );
492 $transformers->register( Span_Prop_Type::get_key(), new Span_Transformer() );
493 }
494
495 private function register_background_styles_transformers( Transformers_Registry $transformers ): void {
496 $transformers->register( Background_Image_Overlay_Prop_Type::get_key(), new Background_Image_Overlay_Transformer() );
497 $transformers->register( Background_Image_Overlay_Size_Scale_Prop_Type::get_key(), new Background_Image_Overlay_Size_Scale_Transformer() );
498 $transformers->register( Background_Image_Position_Offset_Prop_Type::get_key(), new Position_Transformer() );
499 $transformers->register( Background_Color_Overlay_Prop_Type::get_key(), new Background_Color_Overlay_Transformer() );
500 $transformers->register( Background_Overlay_Prop_Type::get_key(), new Background_Overlay_Transformer() );
501 $transformers->register( Background_Prop_Type::get_key(), new Background_Transformer() );
502 $transformers->register( Background_Gradient_Overlay_Prop_Type::get_key(), new Background_Gradient_Overlay_Transformer() );
503 }
504
505 private function register_filter_styles_transformers( Transformers_Registry $transformers ): void {
506 $transformers->register( Filter_Prop_Type::get_key(), new Filter_Transformer() );
507 $transformers->register( Backdrop_Filter_Prop_Type::get_key(), new Filter_Transformer() );
508 $transformers->register( Transition_Prop_Type::get_key(), new Transition_Transformer() );
509 $transformers->register( Color_Stop_Prop_Type::get_key(), new Color_Stop_Transformer() );
510 $transformers->register( Gradient_Color_Stop_Prop_Type::get_key(), new Combine_Array_Transformer( ',' ) );
511 $transformers->register( Position_Prop_Type::get_key(), new Position_Transformer() );
512 }
513
514 private function register_transform_styles_transformers( Transformers_Registry $transformers ): void {
515 $transformers->register( Transform_Move_Prop_Type::get_key(), new Transform_Move_Transformer() );
516 $transformers->register( Transform_Scale_Prop_Type::get_key(), new Transform_Scale_Transformer() );
517 $transformers->register( Transform_Rotate_Prop_Type::get_key(), new Transform_Rotate_Transformer() );
518 $transformers->register( Transform_Skew_Prop_Type::get_key(), new Transform_Skew_Transformer() );
519 $transformers->register( Transform_Functions_Prop_Type::get_key(), new Transform_Functions_Transformer() );
520 $transformers->register( Transform_Origin_Prop_Type::get_key(), new Transform_Origin_Transformer() );
521 $transformers->register( Perspective_Origin_Prop_Type::get_key(), new Perspective_Origin_Transformer() );
522 $transformers->register(
523 Transform_Prop_Type::get_key(),
524 new Multi_Props_Transformer(
525 [ 'transform-functions', 'transform-origin', 'perspective', 'perspective-origin' ],
526 fn( $_, $key ) => 'transform-functions' === $key ? 'transform' : $key
527 )
528 );
529 }
530
531 private function register_layout_styles_transformers( Transformers_Registry $transformers ): void {
532 $transformers->register(
533 Border_Radius_Prop_Type::get_key(),
534 new Multi_Props_Transformer( [ 'start-start', 'start-end', 'end-start', 'end-end' ], fn ( $_, $key ) => "border-{$key}-radius" )
535 );
536 $transformers->register(
537 Border_Width_Prop_Type::get_key(),
538 new Multi_Props_Transformer( [ 'block-start', 'block-end', 'inline-start', 'inline-end' ], fn ( $_, $key ) => "border-{$key}-width" )
539 );
540 $transformers->register(
541 Layout_Direction_Prop_Type::get_key(),
542 new Multi_Props_Transformer( [ 'column', 'row' ], fn ( $prop_key, $key ) => "{$key}-{$prop_key}" )
543 );
544 $transformers->register(
545 Dimensions_Prop_Type::get_key(),
546 new Multi_Props_Transformer( [ 'block-start', 'block-end', 'inline-start', 'inline-end' ], fn ( $prop_key, $key ) => "{$prop_key}-{$key}" )
547 );
548 }
549
550 public function register_import_transformers( Transformers_Registry $transformers ) {
551 $transformers->register_fallback( new Import_Export_Plain_Transformer() );
552
553 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Import_Transformer() );
554 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Import_Transformer() );
555 }
556
557 public function register_export_transformers( Transformers_Registry $transformers ) {
558 $transformers->register_fallback( new Import_Export_Plain_Transformer() );
559
560 $transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Export_Transformer() );
561 $transformers->register( Svg_Src_Prop_Type::get_key(), new Svg_Src_Export_Transformer() );
562 }
563
564 public function register_plain_transformers( Transformers_Registry $transformers ) {
565 $transformers->register_fallback( new Plain_Transformer() );
566 }
567
568 private function register_settings_resolvers( Plain_Resolvers_Registry $registry ): void {
569 $registry->register_fallback( new Passthrough_Plain_Resolver() );
570 $registry->register( Number_Prop_Type::get_key(), new Number_Plain_Resolver() );
571 $registry->register( Boolean_Prop_Type::get_key(), new Boolean_Plain_Resolver() );
572 $registry->register( String_Prop_Type::get_key(), new String_Plain_Resolver() );
573 $registry->register( Size_Prop_Type::get_key(), new Size_Plain_Resolver() );
574 }
575
576 public function get_settings_plain_values_resolver(): Plain_Values_Resolver {
577 static $resolver = null;
578
579 if ( null !== $resolver ) {
580 return $resolver;
581 }
582
583 $registry = new Plain_Resolvers_Registry();
584
585 do_action( 'elementor/atomic-widgets/settings-resolvers/register', $registry );
586
587 $resolver = new Plain_Values_Resolver( $registry );
588
589 $registry->register( Dynamic_Prop_Type::get_key(), new Dynamic_Plain_Resolver( $resolver ) );
590 $registry->register( Html_V3_Prop_Type::get_key(), new Html_V3_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 '.e-background-video { position: relative; overflow: hidden; }',
653 '.e-background-video__media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; z-index: 0; }',
654 '.e-background-video__content { position: relative; z-index: 1; flex: 1 1 auto; }',
655 // Editor empty state: content is a nested flex child inside padded root (overflow:hidden).
656 // Let content shrink to the inner flex area, then grow the empty-view to fill it.
657 '.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; }',
658 '.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%; }',
659 '.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%; }',
660 '.e-background-video__controls { z-index: 2; }',
661 '.e-background-video__play, .e-background-video__pause { appearance: none; -webkit-appearance: none; }',
662 '.e-background-video.e-background-video--playing .e-background-video__play { display: none; }',
663 '.e-background-video.e-background-video--paused .e-background-video__pause { display: none; }',
664 // No state pinned (editor "States" unselected): hide both buttons. The two `:not` guards lift
665 // specificity above the atomic base style so `display: none` wins. On the frontend Alpine always
666 // sets one of the state classes from real playback, so exactly one button shows there.
667 '.e-background-video:not(.e-background-video--playing):not(.e-background-video--paused) .e-background-video__play,',
668 '.e-background-video:not(.e-background-video--playing):not(.e-background-video--paused) .e-background-video__pause { display: none; }',
669 // Accordion: `<summary>` already loses its native marker via `display: flex` on the header's
670 // base style in Chrome/Firefox, but Safari renders `::-webkit-details-marker` regardless of
671 // `display`, so a stray triangle would sit next to our chevron unless the pseudo-element is
672 // killed explicitly. `list-style: none` is kept for completeness (browsers that box the
673 // marker as a list-item marker box), the `::-webkit-details-marker` rule is what actually
674 // fixes Safari.
675 '.e-accordion-item-header-base { list-style: none; }',
676 '.e-accordion-item-header-base::-webkit-details-marker { display: none; }',
677 // Animated expand/collapse via `::details-content` (block-size 0 -> auto) needs
678 // `interpolate-size: allow-keywords` on the <details> element to let `block-size: auto`
679 // participate in the transition. Graceful degradation is deliberate here, but the two failure
680 // modes are different: `interpolate-size` is a real CSS property with a valid selector
681 // (`.e-accordion-item-base`), so that rule always PARSES everywhere — an unsupporting browser
682 // just drops the one unknown *declaration* inside it (inert on its own; harmless). The two
683 // `::details-content` rules are different: `::details-content` is an unrecognised
684 // pseudo-element there, which invalidates the *whole selector*, so the *entire rule* is
685 // dropped, not just a declaration. That whole-rule drop is what structurally guarantees
686 // "collapse to 0" and "expand on [open]" can never apply one without the other — both live
687 // behind the identical `::details-content` requirement, so an unsupporting browser parses
688 // neither and simply keeps the browser's native <details> toggle (content already shown/hidden
689 // correctly without any CSS from us): an instant toggle, never a silently blanked panel.
690 '.e-accordion-item-base { interpolate-size: allow-keywords; }',
691 '.e-accordion-item-base::details-content {',
692 'block-size: 0; overflow: hidden;',
693 'transition: block-size .3s ease, content-visibility .3s ease allow-discrete;',
694 '}',
695 '.e-accordion-item-base[open]::details-content { block-size: auto; }',
696 // Accordion icon slot: see docs/accordion_v4_icon_slot_behaviors.md
697 '.e-accordion-item-icon-base.e-accordion-item-icon-base .e-svg-base { width: auto; height: 100%; max-width: 100%; }',
698 '.e-accordion-item-icon-base.e-accordion-item-icon-base .e-svg-base svg { width: auto !important; }',
699 '.e-accordion-item-icon-base svg { transition: transform .3s ease; }',
700 '.e-accordion-item-base[open] > summary .e-accordion-item-icon-base svg { transform: rotate(180deg); }',
701 ] );
702 wp_add_inline_style( 'elementor-frontend', $inline_css );
703 wp_add_inline_style( 'elementor-editor', $inline_css );
704 }
705
706 private function enqueue_promotion_styles() {
707 if ( \Elementor\Utils::has_pro() ) {
708 return;
709 }
710
711 wp_enqueue_style(
712 'elementor-atomic-widgets-promotion-fonts',
713 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap',
714 [],
715 ELEMENTOR_VERSION
716 );
717
718 wp_enqueue_style(
719 'elementor-atomic-widgets-promotion',
720 $this->get_css_assets_url( 'modules/atomic-widgets/editor' ),
721 [ 'elementor-atomic-widgets-promotion-fonts' ],
722 ELEMENTOR_VERSION
723 );
724 }
725 }
726