import { merge } from 'lodash'; import { applyFilters } from '@wordpress/hooks'; import conditionCheck from '../control-condition-check'; import { maybeDecode } from '../encode-decode'; const { controls: registeredControls } = window.VPGutenbergVariables; /** * Prepare styles from params * Params example: array( 'element' => '$ .inner-selector', 'property' => 'height', 'mask' => '$px', ) * * @param {string} selector CSS selector. * @param {Mixed} value Property value. * @param {Array} params Output params. * * @return {string} */ export function prepareStylesFromParams(selector, value, params) { if ( !selector || typeof value === 'undefined' || value === '' || value === null || typeof params.property === 'undefined' ) { return false; } // Value mask. if (typeof params.mask !== 'undefined') { value = params.mask.replace('$', value); } // Custom selector mask. if (typeof params.element !== 'undefined' && /\$/g.test(params.element)) { selector = params.element.replace('$', selector); } else { selector += typeof params.element !== 'undefined' ? ` ${params.element}` : ''; } return { [selector]: { [params.property]: value, }, }; } /** * Check if these control has dynamic CSS. * * @param {string} controlName control name. * * @return {boolean} */ export function hasDynamicCSS(controlName) { return ( typeof registeredControls[controlName] !== 'undefined' && typeof registeredControls[controlName].style !== 'undefined' && registeredControls[controlName].style.length ); } /** * Get dynamic CSS from options. * * @param {Array} options block options. * * @return {string} */ export default function getDynamicCSS(options) { let result = ''; let selector = ''; if (typeof options.block_id !== 'undefined' && options.block_id) { selector = options.block_id; } else if (typeof options.id !== 'undefined' && options.id) { selector = options.id; } if (!selector) { return result; } selector = `.vp-id-${selector}`; let controlStylesObject = {}; // Controls styles. Object.keys(registeredControls).forEach((k) => { const control = registeredControls[k]; let allow = typeof control.style !== 'undefined' && control.style; // Check condition. if ( allow && typeof control.condition !== 'undefined' && control.condition.length ) { allow = conditionCheck(control.condition, options); } // Prepare styles. if (allow) { control.style.forEach((data) => { let val = options[control.name]; val = applyFilters( 'vpf.editor.controls-dynamic-css-value', val, options, control, selector, data ); // Prepare Aspect Ratio control value. if (control.type && control.type === 'aspect_ratio' && val) { const ratioArray = val.split(':'); if (ratioArray[0] && ratioArray[1]) { val = `${100 * (ratioArray[1] / ratioArray[0])}%`; } } let stylesObject = prepareStylesFromParams(selector, val, data); stylesObject = applyFilters( 'vpf.editor.controls-dynamic-css-styles-object', stylesObject, selector, val, data, options, control ); if (stylesObject) { controlStylesObject = merge( controlStylesObject, stylesObject ); } }); } }); // Prepare CSS of controls. Object.keys(controlStylesObject).forEach((sel) => { result += `${sel} {\n`; Object.keys(controlStylesObject[sel]).forEach((prop) => { result += ` ${prop}: ${controlStylesObject[sel][prop]};\n`; }); result += `}\n`; }); // Custom CSS. if (typeof options.custom_css !== 'undefined' && options.custom_css) { let customCss = options.custom_css; // Decode. customCss = maybeDecode(customCss); // replace 'selector' to actual css selector. customCss = customCss.replace(/selector/g, selector); // a little security fix. customCss = customCss.replace(/<\//g, '</'); result += customCss; } return result; }