: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
// eslint-disable-next-line no-console
* Get the current style attributes state.
* @param {Object} props Block properties.
* @return {boolean} Whether the custom theme is created.
getCurrentStyleAttributes: function getCurrentStyleAttributes(props) {
var _themesData$wpforms$d;
var defaultAttributes = Object.keys((_themesData$wpforms$d = themesData.wpforms.default) === null || _themesData$wpforms$d === void 0 ? void 0 : _themesData$wpforms$d.settings);
var currentStyleAttributes = {};
for (var key in defaultAttributes) {
var _props$attributes$att;
var attr = defaultAttributes[key];
currentStyleAttributes[attr] = (_props$attributes$att = props.attributes[attr]) !== null && _props$attributes$att !== void 0 ? _props$attributes$att : '';
return currentStyleAttributes;
* Maybe create custom theme.
* @param {Object} props Block properties.
* @return {boolean} Whether the custom theme is created.
maybeCreateCustomTheme: function maybeCreateCustomTheme(props) {
var _themesData$wpforms$p;
// eslint-disable-line complexity
var currentStyles = app.getCurrentStyleAttributes(props);
var isWPFormsTheme = !!themesData.wpforms[props.attributes.theme];
var isCustomTheme = !!themesData.custom[props.attributes.theme];
var migrateToCustomTheme = false;
// It is one of the default themes without any changes.
if (isWPFormsTheme && JSON.stringify((_themesData$wpforms$p = themesData.wpforms[props.attributes.theme]) === null || _themesData$wpforms$p === void 0 ? void 0 : _themesData$wpforms$p.settings) === JSON.stringify(currentStyles)) {
var prevAttributes = formSelectorCommon.getBlockRuntimeStateVar(props.clientId, 'prevAttributesState');
// It is a block added in FS 1.0, so it doesn't have a theme.
// The `prevAttributes` is `undefined` means that we are in the first render of the existing block.
if (props.attributes.theme === 'default' && props.attributes.themeName === '' && !prevAttributes) {
migrateToCustomTheme = true;
// It is a modified default theme OR unknown custom theme.
if (isWPFormsTheme || !isCustomTheme || migrateToCustomTheme) {
app.createCustomTheme(props, currentStyles, migrateToCustomTheme);
* @param {Object} props Block properties.
* @param {Object} currentStyles Current style settings.
* @param {boolean} migrateToCustomTheme Whether it is needed to migrate to custom theme.
* @return {boolean} Whether the custom theme is created.
createCustomTheme: function createCustomTheme(props) {
var currentStyles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var migrateToCustomTheme = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
// eslint-disable-line complexity
var themeSlug = props.attributes.theme;
var baseTheme = app.getTheme(props.attributes.theme) || themesData.wpforms.default;
var themeName = baseTheme.name;
themesData.custom = themesData.custom || {};
if (migrateToCustomTheme) {
themeName = strings.theme_custom;
// Determine the theme slug and the number of copies.
themeSlug = themeSlug + '-copy-' + counter;
} while (themesData.custom[themeSlug] && counter < 10000);
var copyStr = counter < 2 ? strings.theme_copy : strings.theme_copy + ' ' + counter;
themeName += ' (' + copyStr + ')';
// The first migrated Custom Theme should be without `(Copy)` suffix.
themeName = migrateToCustomTheme && counter < 2 ? strings.theme_custom : themeName;
// Add the new custom theme.
themesData.custom[themeSlug] = {
settings: currentStyles || app.getCurrentStyleAttributes(props)
app.updateEnabledThemes(themeSlug, themesData.custom[themeSlug]);
// Update the block attributes with the new custom theme settings.
* Maybe create custom theme by given attributes.
* @param {Object} attributes Block properties.
* @return {string} New theme's slug.
maybeCreateCustomThemeFromAttributes: function maybeCreateCustomThemeFromAttributes(attributes) {
var _attributes$themeName;
// eslint-disable-line complexity
var newThemeSlug = attributes.theme;
var existingTheme = app.getTheme(attributes.theme);
var keys = Object.keys(attributes);
var isExistingTheme = Boolean(existingTheme === null || existingTheme === void 0 ? void 0 : existingTheme.settings);
// Check if the theme already exists and has the same settings.
if (!existingTheme.settings[key] || existingTheme.settings[key] !== attributes[key]) {
// The theme exists and has the same settings.
// The theme doesn't exist.
// Normalize the attributes to the default theme settings.
var defaultAttributes = Object.keys(themesData.wpforms.default.settings);
for (var _i in defaultAttributes) {
var attr = defaultAttributes[_i];
newSettings[attr] = (_attributes$attr = attributes[attr]) !== null && _attributes$attr !== void 0 ? _attributes$attr : '';
// Create a new custom theme.
themesData.custom[newThemeSlug] = {
name: (_attributes$themeName = attributes.themeName) !== null && _attributes$themeName !== void 0 ? _attributes$themeName : strings.theme_custom,
app.updateEnabledThemes(newThemeSlug, themesData.custom[newThemeSlug]);
* @param {string} attribute Attribute name.
* @param {string} value New attribute value.
* @param {Object} props Block properties.
updateCustomThemeAttribute: function updateCustomThemeAttribute(attribute, value, props) {
// eslint-disable-line complexity
var themeSlug = props.attributes.theme;
// Skip if it is one of the WPForms themes OR the attribute is not in the theme settings.
if (themesData.wpforms[themeSlug] || attribute !== 'themeName' && !themesData.wpforms.default.settings[attribute]) {
// Skip if the custom theme doesn't exist.
// It should never happen, only in some unique circumstances.
if (!themesData.custom[themeSlug]) {
if (attribute === 'themeName') {
themesData.custom[themeSlug].name = value;
themesData.custom[themeSlug].settings = themesData.custom[themeSlug].settings || themesData.wpforms.default.settings;
themesData.custom[themeSlug].settings[attribute] = value;
// Trigger event for developers.
el.$window.trigger('wpformsFormSelectorUpdateTheme', [themeSlug, themesData.custom[themeSlug], props]);
* Get Themes panel JSX code.
* @param {Object} props Block properties.
* @param {Object} formSelectorCommonModule Common module.
* @param {Object} stockPhotosModule StockPhotos module.
* @return {Object} Themes panel JSX code.
getThemesPanel: function getThemesPanel(props, formSelectorCommonModule, stockPhotosModule) {
// Store common module in app.
formSelectorCommon = formSelectorCommonModule;
state.stockPhotos = stockPhotosModule;
// If there are no themes data, it is necessary to fetch it firstly.
if (!themesData.wpforms) {
// Return empty JSX code.
return /*#__PURE__*/React.createElement(React.Fragment, null);
var handlers = app.getEventHandlers(props);
var showCustomThemeOptions = formSelectorCommonModule.isFullStylingEnabled() && app.maybeCreateCustomTheme(props);
var checked = formSelectorCommonModule.isFullStylingEnabled() ? props.attributes.theme : 'classic';
return /*#__PURE__*/React.createElement(PanelBody, {
className: formSelectorCommon.getPanelClass(props),
}, /*#__PURE__*/React.createElement("p", {
className: "wpforms-gutenberg-panel-notice wpforms-warning wpforms-use-modern-notice"
}, /*#__PURE__*/React.createElement("strong", null, strings.use_modern_notice_head), strings.use_modern_notice_text, " ", /*#__PURE__*/React.createElement("a", {
href: strings.use_modern_notice_link,
}, strings.learn_more)), /*#__PURE__*/React.createElement("p", {
className: "wpforms-gutenberg-panel-notice wpforms-warning wpforms-lead-form-notice",
}, /*#__PURE__*/React.createElement("strong", null, strings.lead_forms_panel_notice_head), strings.lead_forms_panel_notice_text), /*#__PURE__*/React.createElement(RadioGroup, {
className: "wpforms-gutenberg-form-selector-themes-radio-group",
defaultChecked: props.attributes.theme,
onChange: function onChange(value) {
return handlers.selectTheme(value);
}, app.getThemesItemsJSX(props)), showCustomThemeOptions && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextControl, {
className: "wpforms-gutenberg-form-selector-themes-theme-name",
label: strings.theme_name,
value: props.attributes.themeName,
onChange: function onChange(value) {
return handlers.changeThemeName(value);
}), /*#__PURE__*/React.createElement(Button, {
className: "wpforms-gutenberg-form-selector-themes-delete",
onClick: handlers.deleteTheme,
}, strings.theme_delete)));
* Get the Themes panel items JSX code.
* @param {Object} props Block properties.
* @return {Array} Themes items JSX code.
getThemesItemsJSX: function getThemesItemsJSX(props) {
// eslint-disable-line complexity
var allThemesData = app.getAllThemes();
var themes = Object.keys(allThemesData);
var theme, firstThemeSlug;
// Display the current custom theme on the top of the list.
if (!app.isWPFormsTheme(props.attributes.theme)) {
firstThemeSlug = props.attributes.theme;
itemsJsx.push(app.getThemesItemJSX(props.attributes.theme, app.getTheme(props.attributes.theme)));
for (var key in themes) {
if (firstThemeSlug && firstThemeSlug === slug) {
// Ensure that all the theme settings are present.
theme = _objectSpread(_objectSpread({}, allThemesData.default), allThemesData[slug] || {});
theme.settings = _objectSpread(_objectSpread({}, allThemesData.default.settings), theme.settings || {});
itemsJsx.push(app.getThemesItemJSX(slug, theme));
* Get the Themes panel's single item JSX code.
* @param {string} slug Theme slug.
* @param {Object} theme Theme data.
* @return {Object|null} Themes panel single item JSX code.
getThemesItemJSX: function getThemesItemJSX(slug, theme) {
var title = ((_theme$name = theme.name) === null || _theme$name === void 0 ? void 0 : _theme$name.length) > 0 ? theme.name : strings.theme_noname;
return /*#__PURE__*/React.createElement(Radio, {
}, /*#__PURE__*/React.createElement("div", {
className: app.isDisabledTheme(slug) ? 'wpforms-gutenberg-form-selector-themes-radio-disabled' : ''
}, /*#__PURE__*/React.createElement("div", {
className: "wpforms-gutenberg-form-selector-themes-radio-title"
}, title)), /*#__PURE__*/React.createElement(ColorIndicator, {
colorValue: theme.settings.buttonBackgroundColor,
title: strings.button_background
}), /*#__PURE__*/React.createElement(ColorIndicator, {
colorValue: theme.settings.buttonTextColor,
title: strings.button_text
}), /*#__PURE__*/React.createElement(ColorIndicator, {
colorValue: theme.settings.labelColor,
title: strings.field_label
}), /*#__PURE__*/React.createElement(ColorIndicator, {
colorValue: theme.settings.labelSublabelColor,
title: strings.field_sublabel
}), /*#__PURE__*/React.createElement(ColorIndicator, {
colorValue: theme.settings.fieldBorderColor,
title: strings.field_border
* @param {Object} props Block properties.
* @param {string} themeSlug The theme slug.
* @return {boolean} True on success.
setBlockTheme: function setBlockTheme(props, themeSlug) {
if (app.maybeDisplayUpgradeModal(themeSlug)) {
var theme = app.getTheme(themeSlug);
if (!(theme !== null && theme !== void 0 && theme.settings)) {
var attributes = Object.keys(theme.settings);
var block = formSelectorCommon.getBlockContainer(props);
var container = block.querySelector("#wpforms-".concat(props.attributes.formId));
// Overwrite block attributes with the new theme settings.
// It is needed to rely on the theme settings only.
var newProps = _objectSpread(_objectSpread({}, props), {}, {
attributes: _objectSpread(_objectSpread({}, props.attributes), theme.settings)
// Update the preview with the new theme settings.
for (var key in attributes) {
var attr = attributes[key];
theme.settings[attr] = theme.settings[attr] === '0' ? '0px' : theme.settings[attr];
formSelectorCommon.updatePreviewCSSVarValue(attr, theme.settings[attr], container, newProps);
// Prepare the new attributes to be set.
var setAttributes = _objectSpread({
if (props.setAttributes) {
// Update the block attributes with the new theme settings.
props.setAttributes(setAttributes);
// Trigger event for developers.
el.$window.trigger('wpformsFormSelectorSetTheme', [block, themeSlug, props]);
* Maybe display upgrades modal in Lite.
* @param {string} themeSlug The theme slug.
* @return {boolean} True if modal was displayed.
maybeDisplayUpgradeModal: function maybeDisplayUpgradeModal(themeSlug) {
if (!app.isDisabledTheme(themeSlug)) {
formSelectorCommon.education.showProModal('themes', strings.themes);
formSelectorCommon.education.showLicenseModal('themes', strings.themes, 'select-theme');
* Get themes panel event handlers.
* @param {Object} props Block properties.
getEventHandlers: function getEventHandlers(props) {
// eslint-disable-line max-lines-per-function
var commonHandlers = formSelectorCommon.getSettingsFieldsHandlers(props);
* Select theme event handler.
* @param {string} value New attribute value.
selectTheme: function selectTheme(value) {
if (!app.setBlockTheme(props, value)) {
// Maybe open Stock Photo installation window.
state === null || state === void 0 || (_state$stockPhotos = state.stockPhotos) === null || _state$stockPhotos === void 0 || _state$stockPhotos.onSelectTheme(value, props, app, commonHandlers);
var block = formSelectorCommon.getBlockContainer(props);
formSelectorCommon.setTriggerServerRender(false);
commonHandlers.updateCopyPasteContent();
// Trigger event for developers.
el.$window.trigger('wpformsFormSelectorSelectTheme', [block, props, value]);
* Change theme name event handler.
* @param {string} value New attribute value.
changeThemeName: function changeThemeName(value) {
formSelectorCommon.setTriggerServerRender(false);
app.updateCustomThemeAttribute('themeName', value, props);
* Delete theme event handler.
deleteTheme: function deleteTheme() {
var deleteThemeSlug = props.attributes.theme;
// Remove theme from the theme storage.
delete themesData.custom[deleteThemeSlug];
// Open the confirmation modal window.
app.deleteThemeModal(props, deleteThemeSlug, handlers);
* Open the theme delete confirmation modal window.
* @param {Object} props Block properties.
* @param {string} deleteThemeSlug Theme slug.
* @param {Object} handlers Block event handlers.
deleteThemeModal: function deleteThemeModal(props, deleteThemeSlug, handlers) {
var confirm = strings.theme_delete_confirm.replace('%1$s', "<b>".concat(props.attributes.themeName, "</b>"));
var content = "<p class=\"wpforms-theme-delete-text\">".concat(confirm, " ").concat(strings.theme_delete_cant_undone, "</p>");
title: strings.theme_delete_title,
icon: 'wpforms-exclamation-circle',
text: strings.theme_delete_yes,