: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Set of key codes upon which typing is to be initiated on a keydown event.
const KEY_DOWN_ELIGIBLE_KEY_CODES = new Set([external_wp_keycodes_namespaceObject.UP, external_wp_keycodes_namespaceObject.RIGHT, external_wp_keycodes_namespaceObject.DOWN, external_wp_keycodes_namespaceObject.LEFT, external_wp_keycodes_namespaceObject.ENTER, external_wp_keycodes_namespaceObject.BACKSPACE]);
* Returns true if a given keydown event can be inferred as intent to start
* typing, or false otherwise. A keydown is considered eligible if it is a
* text navigation without shift active.
* @param {KeyboardEvent} event Keydown event to test.
* @return {boolean} Whether event is eligible to start typing.
function isKeyDownEligibleForStartTyping(event) {
return !shiftKey && KEY_DOWN_ELIGIBLE_KEY_CODES.has(keyCode);
* Removes the `isTyping` flag when the mouse moves in the document of the given
function useMouseMoveTypingReset() {
const isTyping = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).isTyping(), []);
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
return (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
* On mouse move, unset typing flag if user has moved cursor.
* @param {MouseEvent} event Mousemove event.
function stopTypingOnMouseMove(event) {
// We need to check that the mouse really moved because Safari
// triggers mousemove events when shift or ctrl are pressed.
if (lastClientX && lastClientY && (lastClientX !== clientX || lastClientY !== clientY)) {
ownerDocument.addEventListener('mousemove', stopTypingOnMouseMove);
ownerDocument.removeEventListener('mousemove', stopTypingOnMouseMove);
}, [isTyping, stopTyping]);
* Sets and removes the `isTyping` flag based on user actions:
* - Sets the flag if the user types within the given element.
* - Removes the flag when the user selects some text, focusses a non-text
* field, presses ESC or TAB, or moves the mouse in the document.
function useTypingObserver() {
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
const ref1 = useMouseMoveTypingReset();
const ref2 = (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
const selection = defaultView.getSelection();
// Listeners to stop typing should only be added when typing.
// Listeners to start typing should only be added when not typing.
* Stops typing when focus transitions to a non-text field element.
* @param {FocusEvent} event Focus event.
function stopTypingOnNonTextField(event) {
// Since focus to a non-text field via arrow key will trigger
// before the keydown event, wait until after current stack
// before evaluating whether typing is to be stopped. Otherwise,
timerId = defaultView.setTimeout(() => {
if (!(0,external_wp_dom_namespaceObject.isTextField)(target)) {
* Unsets typing flag if user presses Escape while typing flag is
* @param {KeyboardEvent} event Keypress or keydown event to
function stopTypingOnEscapeKey(event) {
if (keyCode === external_wp_keycodes_namespaceObject.ESCAPE || keyCode === external_wp_keycodes_namespaceObject.TAB) {
* On selection change, unset typing flag if user has made an
* uncollapsed (shift) selection.
function stopTypingOnSelectionUncollapse() {
if (!selection.isCollapsed) {
node.addEventListener('focus', stopTypingOnNonTextField);
node.addEventListener('keydown', stopTypingOnEscapeKey);
ownerDocument.addEventListener('selectionchange', stopTypingOnSelectionUncollapse);
defaultView.clearTimeout(timerId);
node.removeEventListener('focus', stopTypingOnNonTextField);
node.removeEventListener('keydown', stopTypingOnEscapeKey);
ownerDocument.removeEventListener('selectionchange', stopTypingOnSelectionUncollapse);
* Handles a keypress or keydown event to infer intention to start
* @param {KeyboardEvent} event Keypress or keydown event to interpret.
function startTypingInTextField(event) {
// Abort early if already typing, or key press is incurred outside a
// text field (e.g. arrow-ing through toolbar buttons).
// Ignore typing if outside the current DOM container
if (!(0,external_wp_dom_namespaceObject.isTextField)(target) || !node.contains(target)) {
// Special-case keydown because certain keys do not emit a keypress
// event. Conversely avoid keydown as the canonical event since
// there are many keydown which are explicitly not targeted for
if (type === 'keydown' && !isKeyDownEligibleForStartTyping(event)) {
node.addEventListener('keypress', startTypingInTextField);
node.addEventListener('keydown', startTypingInTextField);
node.removeEventListener('keypress', startTypingInTextField);
node.removeEventListener('keydown', startTypingInTextField);
}, [isTyping, startTyping, stopTyping]);
return (0,external_wp_compose_namespaceObject.useMergeRefs)([ref1, ref2]);
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
ref: useTypingObserver(),
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/observe-typing/README.md
/* harmony default export */ const observe_typing = (ObserveTyping);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-list/index.js
const block_list_IntersectionObserver = (0,external_wp_element_namespaceObject.createContext)();
const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap();
function block_list_Root({
const isLargeViewport = (0,external_wp_compose_namespaceObject.useViewportMatch)('medium');
temporarilyEditingAsBlocks
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
getTemporarilyEditingAsBlocks,
} = unlock(select(store));
isOutlineMode: outlineMode && !isTyping(),
editorMode: __unstableGetEditorMode(),
temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks()
const registry = (0,external_wp_data_namespaceObject.useRegistry)();
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
const delayedBlockVisibilityUpdates = (0,external_wp_compose_namespaceObject.useDebounce)((0,external_wp_element_namespaceObject.useCallback)(() => {
pendingBlockVisibilityUpdatesPerRegistry.get(registry).forEach(([id, isIntersecting]) => {
updates[id] = isIntersecting;
setBlockVisibility(updates);
const intersectionObserver = (0,external_wp_element_namespaceObject.useMemo)(() => {
IntersectionObserver: Observer
return new Observer(entries => {
if (!pendingBlockVisibilityUpdatesPerRegistry.get(registry)) {
pendingBlockVisibilityUpdatesPerRegistry.set(registry, []);
for (const entry of entries) {
const clientId = entry.target.getAttribute('data-block');
pendingBlockVisibilityUpdatesPerRegistry.get(registry).push([clientId, entry.isIntersecting]);
delayedBlockVisibilityUpdates();
const innerBlocksProps = useInnerBlocksProps({
ref: (0,external_wp_compose_namespaceObject.useMergeRefs)([useBlockSelectionClearer(), useInBetweenInserter(), useTypingObserver()]),
className: dist_clsx('is-root-container', className, {
'is-outline-mode': isOutlineMode,
'is-focus-mode': isFocusMode && isLargeViewport,
'is-navigate-mode': editorMode === 'navigation'
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(block_list_IntersectionObserver.Provider, {
value: intersectionObserver,
children: [/*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
}), !!temporarilyEditingAsBlocks && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(StopEditingAsBlocksOnOutsideSelect, {
clientId: temporarilyEditingAsBlocks
function StopEditingAsBlocksOnOutsideSelect({
} = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
const isBlockOrDescendantSelected = (0,external_wp_data_namespaceObject.useSelect)(select => {
return isBlockSelected(clientId) || hasSelectedInnerBlock(clientId, true);
(0,external_wp_element_namespaceObject.useEffect)(() => {
if (!isBlockOrDescendantSelected) {
stopEditingAsBlocks(clientId);
}, [isBlockOrDescendantSelected, clientId, stopEditingAsBlocks]);
function BlockList(settings) {
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Provider, {
value: DEFAULT_BLOCK_EDIT_CONTEXT,
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_list_Root, {
const block_list_EMPTY_ARRAY = [];
const block_list_EMPTY_SET = new Set();
renderAppender: CustomAppender,
__experimentalAppenderTagName,
// Avoid passing CustomAppender to useSelect because it could be a new
// function on every render.
const hasAppender = CustomAppender !== false;
const hasCustomAppender = !!CustomAppender;
} = (0,external_wp_data_namespaceObject.useSelect)(select => {
getSelectedBlockClientId,
getSelectedBlockClientIds,
__unstableGetVisibleBlocks,
const _order = getBlockOrder(rootClientId);
if (getSettings().__unstableIsPreviewMode) {
selectedBlocks: block_list_EMPTY_ARRAY,
visibleBlocks: block_list_EMPTY_SET
const selectedBlockClientId = getSelectedBlockClientId();
selectedBlocks: getSelectedBlockClientIds(),
visibleBlocks: __unstableGetVisibleBlocks(),
shouldRenderAppender: hasAppender && __unstableGetEditorMode() !== 'zoom-out' && (hasCustomAppender ? !getTemplateLock(rootClientId) && getBlockEditingMode(rootClientId) !== 'disabled' : rootClientId === selectedBlockClientId || !rootClientId && !selectedBlockClientId && !_order.length)
}, [rootClientId, hasAppender, hasCustomAppender]);
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsxs)(LayoutProvider, {
children: [order.map(clientId => /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_data_namespaceObject.AsyncModeProvider, {
// Only provide data asynchronously if the block is
// not visible and not selected.
!visibleBlocks.has(clientId) && !selectedBlocks.includes(clientId),
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(block_list_block, {
rootClientId: rootClientId,
}, clientId)), order.length < 1 && placeholder, shouldRenderAppender && /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(BlockListAppender, {
tagName: __experimentalAppenderTagName,
rootClientId: rootClientId,
CustomAppender: CustomAppender
function BlockListItems(props) {
// This component needs to always be synchronous as it's the one changing
// the async mode depending on the block selection.
return /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(external_wp_data_namespaceObject.AsyncModeProvider, {
children: /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)(Items, {
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/block-tools/use-block-toolbar-popover-props.js
// By default the toolbar sets the `shift` prop. If the user scrolls the page
// down the toolbar will stay on screen by adopting a sticky position at the
// When there isn't enough height between the top of the block and the editor
// canvas, the `shift` prop is set to `false`, as it will cause the block to be
// obscured. The `flip` behavior is enabled, which positions the toolbar below
// the block. This only happens if the block is smaller than the viewport, as
// otherwise the toolbar will be off-screen.
const RESTRICTED_HEIGHT_PROPS = {
* Get the popover props for the block toolbar, determined by the space at the top of the canvas and the toolbar height.
* @param {Element} contentElement The DOM element that represents the editor content or canvas.
* @param {Element} selectedBlockElement The outer DOM element of the first selected block.
* @param {Element} scrollContainer The scrollable container for the contentElement.
* @param {number} toolbarHeight The height of the toolbar in pixels.
* @param {boolean} isSticky Whether or not the selected block is sticky or fixed.
* @return {Object} The popover props used to determine the position of the toolbar.
function getProps(contentElement, selectedBlockElement, scrollContainer, toolbarHeight, isSticky) {
if (!contentElement || !selectedBlockElement) {
// Get how far the content area has been scrolled.
const scrollTop = scrollContainer?.scrollTop || 0;
const blockRect = selectedBlockElement.getBoundingClientRect();
const contentRect = contentElement.getBoundingClientRect();
// Get the vertical position of top of the visible content area.
const topOfContentElementInViewport = scrollTop + contentRect.top;
// The document element's clientHeight represents the viewport height.
const viewportHeight = contentElement.ownerDocument.documentElement.clientHeight;
// The restricted height area is calculated as the sum of the