PluginProbe
Elementor Website Builder – more than just a page builder / 3.30.0-dev3
Elementor Website Builder – more than just a page builder v3.30.0-dev3
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 / styles / styles-renderer.php

styles-renderer.php in Elementor Website Builder – more than just a page builder 3.30.0-dev3, at modules/atomic-widgets/styles/styles-renderer.php

169 lines 4.3 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\Styles;
4
5 use Elementor\Core\Utils\Collection;
6 use Elementor\Modules\AtomicWidgets\PropsResolver\Render_Props_Resolver;
7
8 class Styles_Renderer {
9 const DEFAULT_SELECTOR_PREFIX = '.elementor';
10
11 /**
12 * @var array<string, array{direction: 'min' | 'max', value: int, is_enabled: boolean}>
13 */
14 private array $breakpoints;
15
16 private $on_prop_transform;
17
18 private string $selector_prefix;
19
20 /**
21 * @param array<string, array{direction: 'min' | 'max', value: int, is_enabled: boolean}> $breakpoints
22 * @param string $selector_prefix
23 */
24 private function __construct( array $breakpoints, string $selector_prefix = self::DEFAULT_SELECTOR_PREFIX ) {
25 $this->breakpoints = $breakpoints;
26 $this->selector_prefix = $selector_prefix;
27 }
28
29 public static function make( array $breakpoints, string $selector_prefix = self::DEFAULT_SELECTOR_PREFIX ): self {
30 return new self( $breakpoints, $selector_prefix );
31 }
32
33 /**
34 * Render the styles to a CSS string.
35 *
36 * Styles format:
37 * array<int, array{
38 * id: string,
39 * type: string,
40 * cssName: string | null,
41 * variants: array<int, array{
42 * props: array<string, mixed>,
43 * meta: array<string, mixed>
44 * }>
45 * }>
46 *
47 * @param array $styles Array of style definitions.
48 *
49 * @return string Rendered CSS string.
50 */
51 public function render( array $styles ): string {
52 $css_style = [];
53
54 foreach ( $styles as $style_def ) {
55 $style = $this->style_definition_to_css_string( $style_def );
56 $css_style[] = $style;
57 }
58
59 return implode( '', $css_style );
60 }
61
62 public function on_prop_transform( callable $callback ): self {
63 $this->on_prop_transform = $callback;
64
65 return $this;
66 }
67
68 private function style_definition_to_css_string( array $style ): string {
69 $base_selector = $this->get_base_selector( $style );
70
71 if ( ! $base_selector ) {
72 return '';
73 }
74
75 $stylesheet = [];
76
77 foreach ( $style['variants'] as $variant ) {
78 $style_declaration = $this->variant_to_css_string( $base_selector, $variant );
79
80 if ( $style_declaration ) {
81 $stylesheet[] = $style_declaration;
82 }
83 }
84
85 return implode( '', $stylesheet );
86 }
87
88 private function get_base_selector( array $style_def ): ?string {
89 $map = [
90 'class' => '.',
91 ];
92
93 if (
94 isset( $style_def['type'] ) &&
95 isset( $style_def['id'] ) &&
96 isset( $map[ $style_def['type'] ] ) &&
97 $style_def['id']
98 ) {
99 $type = $map[ $style_def['type'] ];
100 $name = $style_def['cssName'] ?? $style_def['id'];
101
102 $selector_parts = array_filter( [
103 $this->selector_prefix,
104 "{$type}{$name}",
105 ] );
106
107 return implode( ' ', $selector_parts );
108 }
109
110 return null;
111 }
112
113 private function variant_to_css_string( string $base_selector, array $variant ): string {
114 $css = $this->props_to_css_string( $variant['props'] );
115
116 if ( ! $css ) {
117 return '';
118 }
119
120 $state = isset( $variant['meta']['state'] ) ? ':' . $variant['meta']['state'] : '';
121 $selector = $base_selector . $state;
122
123 $style_declaration = $selector . '{' . $css . '}';
124
125 if ( isset( $variant['meta']['breakpoint'] ) ) {
126 $style_declaration = $this->wrap_with_media_query( $variant['meta']['breakpoint'], $style_declaration );
127 }
128
129 return $style_declaration;
130 }
131
132 private function props_to_css_string( array $props ): string {
133 $schema = Style_Schema::get();
134
135 return Collection::make( Render_Props_Resolver::for_styles()->resolve( $schema, $props ) )
136 ->filter()
137 ->map( function ( $value, $prop ) {
138 if ( $this->on_prop_transform ) {
139 call_user_func( $this->on_prop_transform, $prop, $value );
140 }
141
142 return $prop . ':' . $value . ';';
143 } )
144 ->implode( '' );
145 }
146
147 private function wrap_with_media_query( string $breakpoint_id, string $css ): string {
148 if ( ! isset( $this->breakpoints[ $breakpoint_id ] ) ) {
149 return $css;
150 }
151
152 $breakpoint = $this->breakpoints[ $breakpoint_id ];
153 if ( isset( $breakpoint['is_enabled'] ) && ! $breakpoint['is_enabled'] ) {
154 return '';
155 }
156
157 $size = $this->get_breakpoint_size( $this->breakpoints[ $breakpoint_id ] );
158
159 return $size ? '@media(' . $size . '){' . $css . '}' : $css;
160 }
161
162 private function get_breakpoint_size( array $breakpoint ): ?string {
163 $bound = 'min' === $breakpoint['direction'] ? 'min-width' : 'max-width';
164 $width = $breakpoint['value'] . 'px';
165
166 return "{$bound}:{$width}";
167 }
168 }
169