: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @property {?string} minViewportWidth Minimum viewport size from which type will have fluidity. Optional if size is specified.
* @property {?string} maxViewportWidth Maximum size up to which type will have fluidity. Optional if size is specified.
* @property {?number} scaleFactor A scale factor to determine how fast a font scales within boundaries. Optional.
* @property {?number} minFontSizeFactor How much to scale defaultFontSize by to derive minimumFontSize. Optional.
* @property {?string} minFontSize The smallest a calculated font size may be. Optional.
* Returns a font-size value based on a given font-size preset.
* Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values.
* @param {Object} settings
* @param {boolean|TypographySettings} settings.typography.fluid Whether fluid typography is enabled, and, optionally, fluid font size options.
* @param {Object?} settings.typography.layout Layout options.
* @return {string|*} A font-size value or the value of preset.size.
function getTypographyFontSizeValue(preset, settings) {
if (!isFluidTypographyEnabled(settings?.typography)) {
* Checks whether a font size has explicitly bypassed fluid calculations.
* Also catches falsy values and 0/'0'.
* Fluid calculations cannot be performed on `0`.
if (!defaultSize || '0' === defaultSize || false === preset?.fluid) {
let fluidTypographySettings = getFluidTypographyOptionsFromSettings(settings);
fluidTypographySettings = typeof fluidTypographySettings?.fluid === 'object' ? fluidTypographySettings?.fluid : {};
const fluidFontSizeValue = getComputedFluidTypographyValue({
minimumFontSize: preset?.fluid?.min,
maximumFontSize: preset?.fluid?.max,
minimumFontSizeLimit: fluidTypographySettings?.minFontSize,
maximumViewportWidth: fluidTypographySettings?.maxViewportWidth,
minimumViewportWidth: fluidTypographySettings?.minViewportWidth
if (!!fluidFontSizeValue) {
return fluidFontSizeValue;
function isFluidTypographyEnabled(typographySettings) {
const fluidSettings = typographySettings?.fluid;
return true === fluidSettings || fluidSettings && typeof fluidSettings === 'object' && Object.keys(fluidSettings).length > 0;
* Returns fluid typography settings from theme.json setting object.
* @param {Object} settings Theme.json settings
* @param {Object} settings.typography Theme.json typography settings
* @param {Object} settings.layout Theme.json layout settings
* @return {TypographySettings} Fluid typography settings
function getFluidTypographyOptionsFromSettings(settings) {
const typographySettings = settings?.typography;
const layoutSettings = settings?.layout;
const defaultMaxViewportWidth = getTypographyValueAndUnit(layoutSettings?.wideSize) ? layoutSettings?.wideSize : null;
return isFluidTypographyEnabled(typographySettings) && defaultMaxViewportWidth ? {
maxViewportWidth: defaultMaxViewportWidth,
...typographySettings.fluid
fluid: typographySettings?.fluid
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/global-styles/utils.js
const ROOT_BLOCK_SELECTOR = 'body';
const ROOT_CSS_PROPERTIES_SELECTOR = ':root';
const PRESET_METADATA = [{
path: ['color', 'palette'],
classSuffix: 'background-color',
propertyName: 'background-color'
classSuffix: 'border-color',
propertyName: 'border-color'
path: ['color', 'gradients'],
classSuffix: 'gradient-background',
propertyName: 'background'
path: ['color', 'duotone'],
}) => `url( '#wp-duotone-${slug}' )`,
path: ['shadow', 'presets'],
path: ['typography', 'fontSizes'],
valueFunc: (preset, settings) => getTypographyFontSizeValue(preset, settings),
cssVarInfix: 'font-size',
classSuffix: 'font-size',
propertyName: 'font-size'
path: ['typography', 'fontFamilies'],
cssVarInfix: 'font-family',
classSuffix: 'font-family',
propertyName: 'font-family'
path: ['spacing', 'spacingSizes'],
const STYLE_PATH_TO_CSS_VAR_INFIX = {
'color.background': 'color',
'filter.duotone': 'duotone',
'elements.link.color.text': 'color',
'elements.link.:hover.color.text': 'color',
'elements.link.typography.fontFamily': 'font-family',
'elements.link.typography.fontSize': 'font-size',
'elements.button.color.text': 'color',
'elements.button.color.background': 'color',
'elements.caption.color.text': 'color',
'elements.button.typography.fontFamily': 'font-family',
'elements.button.typography.fontSize': 'font-size',
'elements.heading.color': 'color',
'elements.heading.color.background': 'color',
'elements.heading.typography.fontFamily': 'font-family',
'elements.heading.gradient': 'gradient',
'elements.heading.color.gradient': 'gradient',
'elements.h1.color': 'color',
'elements.h1.color.background': 'color',
'elements.h1.typography.fontFamily': 'font-family',
'elements.h1.color.gradient': 'gradient',
'elements.h2.color': 'color',
'elements.h2.color.background': 'color',
'elements.h2.typography.fontFamily': 'font-family',
'elements.h2.color.gradient': 'gradient',
'elements.h3.color': 'color',
'elements.h3.color.background': 'color',
'elements.h3.typography.fontFamily': 'font-family',
'elements.h3.color.gradient': 'gradient',
'elements.h4.color': 'color',
'elements.h4.color.background': 'color',
'elements.h4.typography.fontFamily': 'font-family',
'elements.h4.color.gradient': 'gradient',
'elements.h5.color': 'color',
'elements.h5.color.background': 'color',
'elements.h5.typography.fontFamily': 'font-family',
'elements.h5.color.gradient': 'gradient',
'elements.h6.color': 'color',
'elements.h6.color.background': 'color',
'elements.h6.typography.fontFamily': 'font-family',
'elements.h6.color.gradient': 'gradient',
'color.gradient': 'gradient',
'typography.fontSize': 'font-size',
'typography.fontFamily': 'font-family'
// A static list of block attributes that store global style preset slugs.
const STYLE_PATH_TO_PRESET_BLOCK_ATTRIBUTE = {
'color.background': 'backgroundColor',
'color.text': 'textColor',
'color.gradient': 'gradient',
'typography.fontSize': 'fontSize',
'typography.fontFamily': 'fontFamily'
function useToolsPanelDropdownMenuProps() {
const isMobile = (0,external_wp_compose_namespaceObject.useViewportMatch)('medium', '<');
// For non-mobile, inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px)
function findInPresetsBy(features, blockName, presetPath, presetProperty, presetValueValue) {
// Block presets take priority above root level presets.
const orderedPresetsByOrigin = [getValueFromObjectPath(features, ['blocks', blockName, ...presetPath]), getValueFromObjectPath(features, presetPath)];
for (const presetByOrigin of orderedPresetsByOrigin) {
// Preset origins ordered by priority.
const origins = ['custom', 'theme', 'default'];
for (const origin of origins) {
const presets = presetByOrigin[origin];
const presetObject = presets.find(preset => preset[presetProperty] === presetValueValue);
if (presetProperty === 'slug') {
// If there is a highest priority preset with the same slug but different value the preset we found was overwritten and should be ignored.
const highestPresetObjectWithSameSlug = findInPresetsBy(features, blockName, presetPath, 'slug', presetObject.slug);
if (highestPresetObjectWithSameSlug[presetProperty] === presetObject[presetProperty]) {
function getPresetVariableFromValue(features, blockName, variableStylePath, presetPropertyValue) {
if (!presetPropertyValue) {
return presetPropertyValue;
const cssVarInfix = STYLE_PATH_TO_CSS_VAR_INFIX[variableStylePath];
const metadata = PRESET_METADATA.find(data => data.cssVarInfix === cssVarInfix);
// The property doesn't have preset data
// so the value should be returned as it is.
return presetPropertyValue;
const presetObject = findInPresetsBy(features, blockName, path, valueKey, presetPropertyValue);
// Value wasn't found in the presets,
// so it must be a custom value.
return presetPropertyValue;
return `var:preset|${cssVarInfix}|${presetObject.slug}`;
function getValueFromPresetVariable(features, blockName, variable, [presetType, slug]) {
const metadata = PRESET_METADATA.find(data => data.cssVarInfix === presetType);
const presetObject = findInPresetsBy(features.settings, blockName, metadata.path, 'slug', slug);
const result = presetObject[valueKey];
return getValueFromVariable(features, blockName, result);
function getValueFromCustomVariable(features, blockName, variable, path) {
var _getValueFromObjectPa;
const result = (_getValueFromObjectPa = getValueFromObjectPath(features.settings, ['blocks', blockName, 'custom', ...path])) !== null && _getValueFromObjectPa !== void 0 ? _getValueFromObjectPa : getValueFromObjectPath(features.settings, ['custom', ...path]);
// A variable may reference another variable so we need recursion until we find the value.
return getValueFromVariable(features, blockName, result);
* Attempts to fetch the value of a theme.json CSS variable.
* @param {Object} features GlobalStylesContext config, e.g., user, base or merged. Represents the theme.json tree.
* @param {string} blockName The name of a block as represented in the styles property. E.g., 'root' for root-level, and 'core/${blockName}' for blocks.
* @param {string|*} variable An incoming style value. A CSS var value is expected, but it could be any value.
* @return {string|*|{ref}} The value of the CSS var, if found. If not found, the passed variable argument.
function getValueFromVariable(features, blockName, variable) {
if (!variable || typeof variable !== 'string') {
if (variable?.ref && typeof variable?.ref === 'string') {
const refPath = variable.ref.split('.');
variable = getValueFromObjectPath(features, refPath);
// Presence of another ref indicates a reference to another dynamic value.
// Pointing to another dynamic value is not supported.
if (!variable || !!variable?.ref) {
const USER_VALUE_PREFIX = 'var:';
const THEME_VALUE_PREFIX = 'var(--wp--';
const THEME_VALUE_SUFFIX = ')';
if (variable.startsWith(USER_VALUE_PREFIX)) {
parsedVar = variable.slice(USER_VALUE_PREFIX.length).split('|');
} else if (variable.startsWith(THEME_VALUE_PREFIX) && variable.endsWith(THEME_VALUE_SUFFIX)) {
parsedVar = variable.slice(THEME_VALUE_PREFIX.length, -THEME_VALUE_SUFFIX.length).split('--');
// We don't know how to parse the value: either is raw of uses complex CSS such as `calc(1px * var(--wp--variable) )`
const [type, ...path] = parsedVar;
return getValueFromPresetVariable(features, blockName, variable, path);
return getValueFromCustomVariable(features, blockName, variable, path);
* Function that scopes a selector with another one. This works a bit like
* SCSS nesting except the `&` operator isn't supported.
* const scope = '.a, .b .c';
* const selector = '> .x, .y';
* const merged = scopeSelector( scope, selector );
* // merged is '.a > .x, .a .y, .b .c > .x, .b .c .y'
* @param {string} scope Selector to scope to.
* @param {string} selector Original selector.
* @return {string} Scoped selector.
function scopeSelector(scope, selector) {
if (!scope || !selector) {
const scopes = scope.split(',');
const selectors = selector.split(',');
const selectorsScoped = [];
scopes.forEach(outer => {
selectors.forEach(inner => {
selectorsScoped.push(`${outer.trim()} ${inner.trim()}`);
return selectorsScoped.join(', ');
* Scopes a collection of selectors for features and subfeatures.
* const scope = '.custom-scope';
* color: '.wp-my-block p',
* typography: { fontSize: '.wp-my-block caption' },
* const result = scopeFeatureSelector( scope, selectors );
* // color: '.custom-scope .wp-my-block p',
* // typography: { fonSize: '.custom-scope .wp-my-block caption' },
* @param {string} scope Selector to scope collection of selectors with.
* @param {Object} selectors Collection of feature selectors e.g.
* @return {Object|undefined} Scoped collection of feature selectors.
function scopeFeatureSelectors(scope, selectors) {
if (!scope || !selectors) {
const featureSelectors = {};
Object.entries(selectors).forEach(([feature, selector]) => {
if (typeof selector === 'string') {
featureSelectors[feature] = scopeSelector(scope, selector);
if (typeof selector === 'object') {
featureSelectors[feature] = {};
Object.entries(selector).forEach(([subfeature, subfeatureSelector]) => {
featureSelectors[feature][subfeature] = scopeSelector(scope, subfeatureSelector);
* Appends a sub-selector to an existing one.
* Given the compounded `selector` "h1, h2, h3"
* and the `toAppend` selector ".some-class" the result will be
* "h1.some-class, h2.some-class, h3.some-class".
* @param {string} selector Original selector.
* @param {string} toAppend Selector to append.
* @return {string} The new selector.
function appendToSelector(selector, toAppend) {
if (!selector.includes(',')) {
return selector + toAppend;
const selectors = selector.split(',');
const newSelectors = selectors.map(sel => sel + toAppend);
return newSelectors.join(',');
* Compares global style variations according to their styles and settings properties.
* const globalStyles = { styles: { typography: { fontSize: '10px' } }, settings: {} };
* const variation = { styles: { typography: { fontSize: '10000px' } }, settings: {} };
* const isEqual = areGlobalStyleConfigsEqual( globalStyles, variation );
* @param {Object} original A global styles object.
* @param {Object} variation A global styles object.
* @return {boolean} Whether `original` and `variation` match.
function areGlobalStyleConfigsEqual(original, variation) {
if (typeof original !== 'object' || typeof variation !== 'object') {
return original === variation;
return es6_default()(original?.styles, variation?.styles) && es6_default()(original?.settings, variation?.settings);
* Generates the selector for a block style variation by creating the
* appropriate CSS class and adding it to the ancestor portion of the block's
* For example, take the Button block which has a compound selector:
* `.wp-block-button .wp-block-button__link`. With a variation named 'custom',
* the class `.is-style-custom` should be added to the `.wp-block-button`
* This function will take into account comma separated and complex selectors.
* @param {string} variation Name for the variation.
* @param {string} blockSelector CSS selector for the block.
* @return {string} CSS selector for the block style variation.
function getBlockStyleVariationSelector(variation, blockSelector) {
const variationClass = `.is-style-${variation}`;
const ancestorRegex = /((?::\([^)]+\))?\s*)([^\s:]+)/;
const addVariationClass = (_match, group1, group2) => {
return group1 + group2 + variationClass;
const result = blockSelector.split(',').map(part => part.replace(ancestorRegex, addVariationClass));
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/global-styles/context.js
const DEFAULT_GLOBAL_STYLES_CONTEXT = {
const GlobalStylesContext = (0,external_wp_element_namespaceObject.createContext)(DEFAULT_GLOBAL_STYLES_CONTEXT);