PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.0.0
GenerateBlocks v2.0.0
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / utils / legacyStyleUtils.js
generateblocks / src / utils Last commit date
add-to-css 3 years ago build-css 6 years ago check-block-version 4 years ago compatible-render 2 years ago filter-attributes 2 years ago flexbox-alignment 6 years ago get-attribute 1 year ago get-background-image 4 years ago get-background-image-url 4 years ago get-content-attribute 2 years ago get-device-type 3 years ago get-dynamic-image 4 years ago get-icon 1 year ago get-image-sizes 4 years ago get-media-url 4 years ago get-responsive-placeholder 2 years ago get-unique-block-names 2 years ago has-numeric-value 4 years ago hex-to-rgba 2 years ago is-flex-item 2 years ago is-numeric 2 years ago sanitize-svg 5 years ago shorthand-css 2 years ago should-rebuild-css 4 years ago sizingValue 3 years ago value-with-unit 2 years ago was-block-just-inserted 4 years ago convertInlineStyleStringToObject.js 1 year ago convertLegacyHtmlAttributes.js 1 year ago get-editor-blocks.js 2 years ago getBlockClasses.js 1 year ago getInnerBlocks.js 1 year ago index.js 1 year ago legacyStyleUtils.js 1 year ago loop-utils.js 1 year ago more-design-options.js 1 year ago noStyleAttributes.js 1 year ago object-is-empty.js 4 years ago sanitizeHtmlAttribute.js 1 year ago selectorShortcuts.js 1 year ago
legacyStyleUtils.js
528 lines
1 import { sprintf } from '@wordpress/i18n';
2
3 import { defaultAtRules, cleanStylesObject, getAtRuleValue } from '@edge22/styles-builder';
4
5 import { noStyleAttributes, hexToRGBA, hasNumericValue } from '@utils';
6
7 export function getLocalBlockStyles( attributeData, blockAttributes ) {
8 return Object.entries( attributeData )
9 .filter( ( [ attributeName, attribute ] ) =>
10 ! noStyleAttributes.includes( attributeName ) && blockAttributes[ attributeName ] !== attribute.default
11 )
12 .reduce( ( result, [ attributeName ] ) => {
13 result[ attributeName ] = blockAttributes[ attributeName ];
14
15 return result;
16 }, {} );
17 }
18
19 export function convertLocalToStyles( attributeData, blockAttributes, hoverSelector = '&:hover' ) {
20 const localBlockStyles = getLocalBlockStyles( attributeData, blockAttributes );
21
22 const addToMedia = ( result, rule, attributeName, value ) => {
23 if ( attributeName.includes( 'Hover' ) ) {
24 result[ rule ][ hoverSelector ][ attributeName ] = value;
25 } else {
26 result[ rule ][ attributeName ] = value;
27 }
28 };
29
30 const tabletMediaQuery = defaultAtRules.find( ( rule ) => 'mediumSmallWidth' === rule.id )?.value ?? '@media (max-width:1024px)';
31 const mobileMediaQuery = defaultAtRules.find( ( rule ) => 'smallWidth' === rule.id )?.value ?? '@media (max-width:767px)';
32
33 const cleanAttributeName = ( attributeName ) => {
34 attributeName = attributeName
35 .replace( 'Tablet', '' )
36 .replace( 'Mobile', '' )
37 .replace( 'Hover', '' )
38 .replace( 'textColor', 'color' )
39 .replace( 'zindex', 'zIndex' );
40
41 const dummyElement = document.createElement( 'div' );
42 const computedStyle = getComputedStyle( dummyElement );
43
44 // Make sure our attributeName is a valid CSS property.
45 if ( attributeName in computedStyle ) {
46 return attributeName;
47 }
48
49 return '';
50 };
51
52 const convertedObject = Object.entries( localBlockStyles )
53 .reduce( ( result, [ attributeName ] ) => {
54 const cleanedAttributeName = cleanAttributeName( attributeName );
55
56 if ( attributeName.includes( 'Tablet' ) && cleanedAttributeName ) {
57 addToMedia( result, tabletMediaQuery, cleanedAttributeName, blockAttributes[ attributeName ] );
58 } else if ( attributeName.includes( 'Mobile' ) && cleanedAttributeName ) {
59 addToMedia( result, mobileMediaQuery, cleanedAttributeName, blockAttributes[ attributeName ] );
60 } else if ( attributeName.includes( 'Hover' ) && cleanedAttributeName ) {
61 result[ hoverSelector ][ cleanedAttributeName ] = blockAttributes[ attributeName ];
62 } else if (
63 'spacing' === attributeName ||
64 'sizing' === attributeName ||
65 'borders' === attributeName ||
66 'typography' === attributeName
67 ) {
68 // Extract values inside 'spacing' and 'sizing' and add them directly to the result
69 Object.entries( blockAttributes[ attributeName ] ).forEach( ( [ key, value ] ) => {
70 const cleanedObjectAttributeName = cleanAttributeName( key );
71
72 if ( key.includes( 'Tablet' ) && cleanedObjectAttributeName ) {
73 addToMedia( result, tabletMediaQuery, cleanedObjectAttributeName, value );
74 } else if ( key.includes( 'Mobile' ) && cleanedObjectAttributeName ) {
75 addToMedia( result, mobileMediaQuery, cleanedObjectAttributeName, value );
76 } else if ( key.includes( 'Hover' ) && cleanedObjectAttributeName ) {
77 result[ hoverSelector ][ cleanedObjectAttributeName ] = value;
78 } else if ( cleanedObjectAttributeName ) {
79 result[ cleanedObjectAttributeName ] = value;
80 }
81 } );
82 } else if ( 'bgImage' === attributeName ) {
83 if ( blockAttributes.bgImage?.image?.url ) {
84 if ( 'pseudo-element' === blockAttributes?.bgOptions?.selector ) {
85 result[ '&:before' ] = {
86 ...result[ '&:before' ],
87 backgroundImage: `url(${ blockAttributes.bgImage.image.url })`,
88 backgroundRepeat: blockAttributes.bgOptions.repeat,
89 backgroundSize: blockAttributes.bgOptions.size,
90 backgroundPosition: blockAttributes.bgOptions.position,
91 backgroundAttachment: blockAttributes.bgOptions.attachment,
92 opacity: blockAttributes.bgOptions.opacity,
93 content: '""',
94 position: 'absolute',
95 top: '0',
96 right: '0',
97 bottom: '0',
98 left: '0',
99 zIndex: '0',
100 };
101 } else {
102 result.backgroundImage = `url(${ blockAttributes.bgImage.image.url })`;
103 result.backgroundRepeat = blockAttributes.bgOptions.repeat;
104 result.backgroundSize = blockAttributes.bgOptions.size;
105 result.backgroundPosition = blockAttributes.bgOptions.position;
106 result.backgroundAttachment = blockAttributes.bgOptions.attachment;
107 }
108 }
109 } else if ( 'gradient' === attributeName && blockAttributes.gradient ) {
110 let gradientColorStopOneValue = '',
111 gradientColorStopTwoValue = '';
112
113 const gradientColorOneValue = hexToRGBA( blockAttributes.gradientColorOne, blockAttributes.gradientColorOneOpacity );
114 const gradientColorTwoValue = hexToRGBA( blockAttributes.gradientColorTwo, blockAttributes.gradientColorTwoOpacity );
115
116 if ( blockAttributes.gradientColorOne && '' !== blockAttributes.gradientColorStopOne ) {
117 gradientColorStopOneValue = ' ' + blockAttributes.gradientColorStopOne + '%';
118 }
119
120 if ( blockAttributes.gradientColorTwo && '' !== blockAttributes.gradientColorStopTwo ) {
121 gradientColorStopTwoValue = ' ' + blockAttributes.gradientColorStopTwo + '%';
122 }
123
124 const gradientValue = 'linear-gradient(' + blockAttributes.gradientDirection + 'deg, ' + gradientColorOneValue + gradientColorStopOneValue + ', ' + gradientColorTwoValue + gradientColorStopTwoValue + ')';
125
126 if ( 'pseudo-element' === blockAttributes.gradientSelector ) {
127 result[ '&:after' ] = {
128 ...result[ '&:after' ],
129 backgroundImage: gradientValue,
130 content: '""',
131 position: 'absolute',
132 top: '0',
133 right: '0',
134 bottom: '0',
135 left: '0',
136 zIndex: '0',
137 pointerEvents: 'none',
138 };
139 } else {
140 result.backgroundImage = gradientValue;
141 }
142 } else if ( 'iconStyles' === attributeName ) {
143 const iconStyles = blockAttributes.iconStyles;
144
145 if ( iconStyles.width ) {
146 result[ '.gb-shape svg' ] = {
147 ...result[ '.gb-shape svg' ],
148 width: iconStyles.width,
149 };
150 }
151
152 if ( iconStyles.height ) {
153 result[ '.gb-shape svg' ] = {
154 ...result[ '.gb-shape svg' ],
155 height: iconStyles.height,
156 };
157 }
158 } else if ( 'useGlobalMaxWidth' === attributeName ) {
159 if ( blockAttributes.useGlobalMaxWidth ) {
160 result.maxWidth = 'var(--gb-container-width)';
161 }
162 } else if ( 'iconColor' === attributeName ) {
163 result[ '.gb-shape svg' ] = {
164 ...result[ '.gb-shape svg' ],
165 color: blockAttributes.iconColor,
166 fill: 'currentColor',
167 };
168 } else if ( 'linkColor' === attributeName ) {
169 result.a = {
170 ...result.a,
171 color: blockAttributes.linkColor,
172 };
173 } else if ( 'linkColorHover' === attributeName ) {
174 result[ 'a:hover' ] = {
175 ...result[ 'a:hover' ],
176 color: blockAttributes.linkColorHover,
177 };
178 } else if ( 'opacities' === attributeName ) {
179 applyEffectsStyles(
180 result,
181 blockAttributes.opacities,
182 blockAttributes.useOpacity,
183 getLegacyOpacityValues
184 );
185 } else if ( 'transitions' === attributeName ) {
186 applyEffectsStyles(
187 result,
188 blockAttributes.transitions,
189 blockAttributes.useTransition,
190 getLegacyTransitionValues
191 );
192 } else if ( 'boxShadows' === attributeName ) {
193 applyEffectsStyles(
194 result,
195 blockAttributes.boxShadows,
196 blockAttributes.useBoxShadow,
197 getLegacyBoxShadowValues
198 );
199 } else if ( 'textShadows' === attributeName ) {
200 applyEffectsStyles(
201 result,
202 blockAttributes.textShadows,
203 blockAttributes.useTextShadow,
204 getLegacyTextShadowValues
205 );
206 } else if ( 'filters' === attributeName ) {
207 applyEffectsStyles(
208 result,
209 blockAttributes.filters,
210 blockAttributes.useFilter,
211 getLegacyFilterValues
212 );
213 } else if ( 'transforms' === attributeName ) {
214 applyEffectsStyles(
215 result,
216 blockAttributes.transforms,
217 blockAttributes.useTransform,
218 getLegacyTransformValues
219 );
220 } else if ( cleanedAttributeName ) {
221 // Handle default case
222 result[ cleanedAttributeName ] = blockAttributes[ attributeName ];
223 }
224
225 return result;
226 }, { [ tabletMediaQuery ]: {}, [ mobileMediaQuery ]: {}, [ hoverSelector ]: {}, '&:before': {}, '&:after': {} } );
227
228 return cleanStylesObject( convertedObject );
229 }
230
231 function getLegacyEffectsSelector( effect ) {
232 const {
233 device = '',
234 state = 'normal',
235 target = 'self',
236 customSelector = '',
237 direction = '',
238 } = effect;
239
240 let atRule = '';
241
242 switch ( device ) {
243 case 'mobile':
244 atRule = getAtRuleValue( 'smallWidth' );
245 break;
246 case 'tablet':
247 atRule = getAtRuleValue( 'mediumSmallWidth' );
248 break;
249 case 'tablet-only':
250 atRule = getAtRuleValue( 'mediumWidth' );
251 break;
252 case 'desktop':
253 atRule = getAtRuleValue( 'largeWidth' );
254 break;
255 }
256
257 let nestedRule = '';
258
259 if ( 'hover' === state ) {
260 nestedRule = '&:hover';
261 }
262
263 switch ( target ) {
264 case 'innerContainer':
265 nestedRule += ' > .gb-container';
266 break;
267 case 'backgroundImage':
268 if ( nestedRule ) {
269 nestedRule += ':before';
270 } else {
271 nestedRule = '&:before';
272 }
273 break;
274 case 'icon':
275 nestedRule += ' .gb-shape';
276 break;
277 case 'accordionContent':
278 nestedRule += ' > .gb-accordion__content';
279 break;
280 case 'customSelector':
281 nestedRule += ' ' + customSelector;
282 break;
283 case 'pseudo-element':
284 const pseudoSelector = direction ? ':after' : ':before';
285
286 if ( nestedRule ) {
287 nestedRule += pseudoSelector;
288 } else {
289 nestedRule = '&' + pseudoSelector;
290 }
291 break;
292 }
293
294 return {
295 atRule,
296 nestedRule,
297 };
298 }
299
300 function applyEffectsStyles( result, effects, useEffect, getValues ) {
301 if ( ! useEffect ) {
302 return;
303 }
304
305 if ( ! Array.isArray( effects ) || 0 === effects.length ) {
306 return;
307 }
308
309 effects.forEach( ( effect ) => {
310 const values = getValues( effect );
311
312 if ( ! values || 0 === Object.keys( values ).length ) {
313 return;
314 }
315
316 const selector = getLegacyEffectsSelector( effect );
317
318 if ( selector?.atRule ) {
319 if ( selector?.nestedRule ) {
320 result[ selector.nestedRule ] = {
321 ...result[ selector.nestedRule ],
322 [ selector.atRule ]: {
323 ...result[ selector.nestedRule ]?.[ selector.atRule ],
324 ...values,
325 },
326 };
327 } else {
328 result[ selector.atRule ] = {
329 ...result[ selector.atRule ],
330 ...values,
331 };
332 }
333 } else if ( selector?.nestedRule ) {
334 result[ selector.nestedRule ] = {
335 ...result[ selector.nestedRule ],
336 ...values,
337 };
338 } else {
339 Object.assign( result, values );
340 }
341 } );
342 }
343
344 function getLegacyOpacityValues( opacity ) {
345 const values = {};
346
347 if ( hasNumericValue( opacity.opacity ) ) {
348 values.opacity = opacity.opacity;
349 }
350
351 if ( opacity.mixBlendMode ) {
352 values.mixBlendMode = opacity.mixBlendMode;
353 }
354
355 return values;
356 }
357
358 function getLegacyTransitionValues( transition ) {
359 const transitionValue = sprintf(
360 '%1$s %2$s %3$s %4$s',
361 transition.property,
362 transition.duration + 's',
363 transition.timingFunction,
364 hasNumericValue( transition.delay ) ? transition.delay + 's' : ''
365 );
366
367 return {
368 transition: transitionValue.trim(),
369 };
370 }
371
372 function getLegacyBoxShadowValues( boxShadow ) {
373 const {
374 inset = '',
375 xOffset = '0',
376 yOffset = '0',
377 blur = '0',
378 spread = '0',
379 color,
380 colorOpacity = '1',
381 } = boxShadow;
382
383 const boxShadowValue = sprintf(
384 '%1$s %2$s %3$s %4$s %5$s %6$s',
385 inset ? 'inset' : '',
386 xOffset ? xOffset + 'px' : '0',
387 yOffset ? yOffset + 'px' : '0',
388 blur ? blur + 'px' : '0',
389 spread ? spread + 'px' : '0',
390 hexToRGBA( color, colorOpacity )
391 );
392
393 return {
394 boxShadow: boxShadowValue.trim(),
395 };
396 }
397
398 function getLegacyTextShadowValues( textShadow ) {
399 const {
400 xOffset = '0',
401 yOffset = '0',
402 blur = '0',
403 color,
404 colorOpacity = '1',
405 } = textShadow;
406
407 const textShadowValue = sprintf(
408 '%1$s %2$s %3$s %4$s',
409 hexToRGBA( color, colorOpacity ),
410 xOffset ? xOffset + 'px' : '0',
411 yOffset ? yOffset + 'px' : '0',
412 blur ? blur + 'px' : '0',
413 );
414
415 return {
416 textShadow: textShadowValue.trim(),
417 };
418 }
419
420 function getLegacyFilterValues( filter ) {
421 const filters = [];
422
423 const {
424 type = '',
425 blur = '',
426 brightness = '',
427 contrast = '',
428 grayscale = '',
429 hueRotate = '',
430 invert = '',
431 saturate = '',
432 sepia = '',
433 } = filter;
434
435 if ( 'blur' === type && hasNumericValue( blur ) ) {
436 filters.push( `blur(${ blur }px)` );
437 }
438
439 if ( 'brightness' === type && hasNumericValue( brightness ) ) {
440 filters.push( `brightness(${ brightness }%)` );
441 }
442
443 if ( 'contrast' === type && hasNumericValue( contrast ) ) {
444 filters.push( `contrast(${ contrast }%)` );
445 }
446
447 if ( 'grayscale' === type && hasNumericValue( grayscale ) ) {
448 filters.push( `grayscale(${ grayscale }%)` );
449 }
450
451 if ( 'hue-rotate' === type && hasNumericValue( hueRotate ) ) {
452 filters.push( `hue-rotate(${ hueRotate }deg)` );
453 }
454
455 if ( 'invert' === type && hasNumericValue( invert ) ) {
456 filters.push( `invert(${ invert }%)` );
457 }
458
459 if ( 'saturate' === type && hasNumericValue( saturate ) ) {
460 filters.push( `saturate(${ saturate }%)` );
461 }
462
463 if ( 'sepia' === type && hasNumericValue( sepia ) ) {
464 filters.push( `sepia(${ sepia }%)` );
465 }
466
467 return {
468 filter: filters.length ? filters.join( ' ' ) : '',
469 };
470 }
471
472 function getLegacyTransformValues( transform ) {
473 const transforms = [];
474
475 const {
476 type = '',
477 translateX = '',
478 translateY = '',
479 rotate = '',
480 skewX = '',
481 skewY = '',
482 scale = '',
483 } = transform;
484
485 if ( 'translate' === type ) {
486 let translateXValue = 0;
487 let translateYValue = 0;
488
489 if ( hasNumericValue( translateX ) ) {
490 translateXValue = translateX + 'px';
491 }
492
493 if ( hasNumericValue( translateY ) ) {
494 translateYValue = translateY + 'px';
495 }
496
497 transforms.push( `translate(${ translateXValue }, ${ translateYValue })` );
498 }
499
500 if ( 'rotate' === type && hasNumericValue( rotate ) ) {
501 transforms.push( `rotate(${ rotate }deg)` );
502 }
503
504 if ( 'skew' === type ) {
505 let skewXValue = 0;
506 let skewYValue = 0;
507
508 if ( hasNumericValue( skewX ) ) {
509 skewXValue = skewX + 'deg';
510 }
511
512 if ( hasNumericValue( skewY ) ) {
513 skewYValue = skewY + 'deg';
514 }
515
516 transforms.push( `skew(${ skewXValue }, ${ skewYValue })` );
517 }
518
519 if ( 'scale' === type && hasNumericValue( scale ) ) {
520 transforms.push( `scale(${ scale })` );
521 transforms.push( 'perspective(1000px)' ); // Activate GPU.
522 }
523
524 return {
525 transform: transforms.length ? transforms.join( ' ' ) : '',
526 };
527 }
528