: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
this.returnFocusWhenClose = returnFocusWhenClose;
// Overridden collapse() function. Mostly call the parent collapse(), but also
// move our .isOpen to false.
// Initially, I tried tracking this with onChangeExpanded(), but it doesn't work
// because the block settings sidebar is a layer "on top of" the G editor sidebar.
// For example, when closing the block settings sidebar, the G
// editor sidebar would display, and onChangeExpanded in
// inspector-section would run with expanded=true, but I want
// isOpen to be false when the block settings is closed.
triggerActiveCallbacks() {
// Manually fire the callbacks associated with moving this.active
// from false to true. "active" is always true for this section,
// and "isContextuallyActive" reflects if the block settings
// sidebar is currently visible, that is, it has replaced the main
// The WP customizer only checks ".isContextuallyActive()" when
// ".active" changes values. But our ".active" never changes value.
// The WP customizer never foresaw a section being used a way we
// fit the block settings sidebar into a section. By manually
// triggering the "this.active" callbacks, we force the WP
// customizer to query our .isContextuallyActive() function and
// update its view of our status.
this.active.callbacks.fireWith(this.active, [false, true]);
;// CONCATENATED MODULE: ./node_modules/@wordpress/customize-widgets/build-module/controls/sidebar-section.js
const getInspectorSectionId = sidebarId => `widgets-inspector-${sidebarId}`;
function getSidebarSection() {
const reduceMotionMediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
let isReducedMotion = reduceMotionMediaQuery.matches;
reduceMotionMediaQuery.addEventListener('change', event => {
isReducedMotion = event.matches;
return class SidebarSection extends customize.Section {
const InspectorSection = getInspectorSection();
this.inspector = new InspectorSection(getInspectorSectionId(this.id), {
title: (0,external_wp_i18n_namespaceObject.__)('Block Settings'),
customizeAction: [(0,external_wp_i18n_namespaceObject.__)('Customizing'), (0,external_wp_i18n_namespaceObject.__)('Widgets'), this.params.title].join(' ▸ ')
customize.section.add(this.inspector);
this.contentContainer[0].classList.add('customize-widgets__sidebar-section');
return this.inspector.expanded();
onChangeExpanded(expanded, _args) {
const controls = this.controls();
controls.forEach(control => {
control.onChangeSectionExpanded?.(expanded, args);
_args.completeCallback?.();
if (args.manualTransition) {
this.contentContainer.addClass(['busy', 'open']);
this.contentContainer.removeClass('is-sub-section-open');
this.contentContainer.closest('.wp-full-overlay').addClass('section-open');
this.contentContainer.addClass(['busy', 'is-sub-section-open']);
this.contentContainer.closest('.wp-full-overlay').addClass('section-open');
this.contentContainer.removeClass('open');
const handleTransitionEnd = () => {
this.contentContainer.removeClass('busy');
this.contentContainer.one('transitionend', handleTransitionEnd);
super.onChangeExpanded(expanded, args);
;// CONCATENATED MODULE: ./node_modules/@wordpress/customize-widgets/build-module/components/sidebar-block-editor/sidebar-adapter.js
function parseWidgetId(widgetId) {
const matches = widgetId.match(/^(.+)-(\d+)$/);
number: parseInt(matches[2], 10)
// Likely an old single widget.
function widgetIdToSettingId(widgetId) {
} = parseWidgetId(widgetId);
return `widget_${idBase}[${number}]`;
return `widget_${idBase}`;
* This is a custom debounce function to call different callbacks depending on
* whether it's the _leading_ call or not.
* @param {Function} leading The callback that gets called first.
* @param {Function} callback The callback that gets called after the first time.
* @param {number} timeout The debounced time in milliseconds.
* @return {Function} The debounced function.
function debounce(leading, callback, timeout) {
function debounced(...args) {
const result = (isLeading ? callback : leading).apply(this, args);
timerID = setTimeout(() => {
debounced.cancel = () => {
constructor(setting, api) {
this.widgetsCache = new WeakMap();
this.subscribers = new Set();
this.history = [this._getWidgetIds().map(widgetId => this.getWidget(widgetId))];
this.historySubscribers = new Set();
// Debounce the input for 1 second.
this._debounceSetHistory = debounce(this._pushHistory, this._replaceHistory, 1000);
this.setting.bind(this._handleSettingChange.bind(this));
this.api.bind('change', this._handleAllSettingsChange.bind(this));
this.undo = this.undo.bind(this);
this.redo = this.redo.bind(this);
this.save = this.save.bind(this);
this.subscribers.add(callback);
this.subscribers.delete(callback);
return this.history[this.historyIndex];
for (const callback of this.subscribers) {
return this.setting.get();
this.history = [...this.history.slice(0, this.historyIndex + 1), this._getWidgetIds().map(widgetId => this.getWidget(widgetId))];
this.historySubscribers.forEach(listener => listener());
this.history[this.historyIndex] = this._getWidgetIds().map(widgetId => this.getWidget(widgetId));
const prevWidgets = this.getWidgets();
this._emit(prevWidgets, this.getWidgets());
_handleAllSettingsChange(setting) {
if (!setting.id.startsWith('widget_')) {
const widgetId = settingIdToWidgetId(setting.id);
if (!this.setting.get().includes(widgetId)) {
const prevWidgets = this.getWidgets();
this._emit(prevWidgets, this.getWidgets());
const widgetModel = wp.customize.Widgets.availableWidgets.findWhere({
let number = widget.number;
if (widgetModel.get('is_multi') && !number) {
widgetModel.set('multi_number', widgetModel.get('multi_number') + 1);
number = widgetModel.get('multi_number');
const settingId = number ? `widget_${widget.idBase}[${number}]` : `widget_${widget.idBase}`;
transport: wp.customize.Widgets.data.selectiveRefreshableWidgets[widgetModel.get('id_base')] ? 'postMessage' : 'refresh',
previewer: this.setting.previewer
const setting = this.api.create(settingId, settingId, '', settingArgs);
setting.set(widget.instance);
const widgetId = settingIdToWidgetId(settingId);
const settingId = widgetIdToSettingId(widget.id);
const setting = this.api(settingId);
const instance = setting.get();
this.widgetsCache.delete(instance);
this.api.remove(settingId);
const prevWidget = this.getWidget(widget.id);
// Bail out update if nothing changed.
if (prevWidget === widget) {
// Update existing setting if only the widget's instance changed.
if (prevWidget.idBase && widget.idBase && prevWidget.idBase === widget.idBase) {
const settingId = widgetIdToSettingId(widget.id);
this.api(settingId).set(widget.instance);
// Otherwise delete and re-create.
this._removeWidget(widget);
return this._createWidget(widget);
} = parseWidgetId(widgetId);
const settingId = widgetIdToSettingId(widgetId);
const setting = this.api(settingId);
const instance = setting.get();
if (this.widgetsCache.has(instance)) {
return this.widgetsCache.get(instance);
this.widgetsCache.set(instance, widget);
_updateWidgets(nextWidgets) {
const addedWidgetIds = [];
const nextWidgetIds = nextWidgets.map(nextWidget => {
if (nextWidget.id && this.getWidget(nextWidget.id)) {
addedWidgetIds.push(null);
return this._updateWidget(nextWidget);
const widgetId = this._createWidget(nextWidget);
addedWidgetIds.push(widgetId);
const deletedWidgets = this.getWidgets().filter(widget => !nextWidgetIds.includes(widget.id));
deletedWidgets.forEach(widget => this._removeWidget(widget));
this.setting.set(nextWidgetIds);
setWidgets(nextWidgets) {
const addedWidgetIds = this._updateWidgets(nextWidgets);
this._debounceSetHistory();
* Undo/Redo related features
return this.historyIndex > 0;
return this.historyIndex < this.history.length - 1;
const currentWidgets = this.getWidgets();
this.historyIndex = historyIndex;
const widgets = this.history[this.historyIndex];
this._updateWidgets(widgets);
this._emit(currentWidgets, this.getWidgets());
this.historySubscribers.forEach(listener => listener());
this._debounceSetHistory.cancel();
this._seek(this.historyIndex - 1);
this._seek(this.historyIndex + 1);
subscribeHistory(listener) {
this.historySubscribers.add(listener);
this.historySubscribers.delete(listener);
this.api.previewer.save();
;// CONCATENATED MODULE: external ["wp","dom"]
const external_wp_dom_namespaceObject = window["wp"]["dom"];
;// CONCATENATED MODULE: ./node_modules/@wordpress/customize-widgets/build-module/controls/inserter-outer-section.js
function getInserterOuterSection() {
const OuterSection = customize.OuterSection;
// Override the OuterSection class to handle multiple outer sections.
// It closes all the other outer sections whenever one is opened.
// The result is that at most one outer section can be opened at the same time.
customize.OuterSection = class extends OuterSection {
onChangeExpanded(expanded, args) {
customize.section.each(section => {
if (section.params.type === 'outer' && section.id !== this.id) {
if (section.expanded()) {
return super.onChangeExpanded(expanded, args);
// Handle constructor so that "params.type" can be correctly pointed to "outer".
customize.sectionConstructor.outer = customize.OuterSection;
return class InserterOuterSection extends customize.OuterSection {
// This is necessary since we're creating a new class which is not identical to the original OuterSection.
// @See https://github.com/WordPress/wordpress-develop/blob/42b05c397c50d9dc244083eff52991413909d4bd/src/js/_enqueues/wp/customize/controls.js#L1427-L1436
this.params.type = 'outer';
this.activeElementBeforeExpanded = null;
const ownerWindow = this.contentContainer[0].ownerDocument.defaultView;
// Handle closing the inserter when pressing the Escape key.
ownerWindow.addEventListener('keydown', event => {
if (this.expanded() && (event.keyCode === external_wp_keycodes_namespaceObject.ESCAPE || event.code === 'Escape') && !event.defaultPrevented) {
(0,external_wp_data_namespaceObject.dispatch)(store).setIsInserterOpened(false);
// Use capture mode to make this run before other event listeners.
this.contentContainer.addClass('widgets-inserter');
// Set a flag if the state is being changed from open() or close().
// Don't propagate the event if it's an internal action to prevent infinite loop.
this.isFromInternalAction = false;
this.expanded.bind(() => {
if (!this.isFromInternalAction) {
// Propagate the event to React to sync the state.
(0,external_wp_data_namespaceObject.dispatch)(store).setIsInserterOpened(this.expanded());
this.isFromInternalAction = false;
const contentContainer = this.contentContainer[0];
this.activeElementBeforeExpanded = contentContainer.ownerDocument.activeElement;
this.isFromInternalAction = true;
// We have to do this in a "completeCallback" or else the elements will not yet be visible/tabbable.
// The first one should be the close button,
// we want to skip it and choose the second one instead, which is the search box.
const searchBox = external_wp_dom_namespaceObject.focus.tabbable.find(contentContainer)[1];
const contentContainer = this.contentContainer[0];
const activeElement = contentContainer.ownerDocument.activeElement;
this.isFromInternalAction = true;
// Return back the focus when closing the inserter.
// Only do this if the active element which triggers the action is inside the inserter,
// (the close button for instance). In that case the focus will be lost.
// Otherwise, we don't hijack the focus when the user is focusing on other elements
// (like the quick inserter).
if (contentContainer.contains(activeElement)) {
// Return back the focus when closing the inserter.
if (this.activeElementBeforeExpanded) {
this.activeElementBeforeExpanded.focus();
;// CONCATENATED MODULE: ./node_modules/@wordpress/customize-widgets/build-module/controls/sidebar-control.js