: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* When the component updates, and there is multi selection, we need to
* select the entire block contents.
return (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
// Allow initialPosition to bypass focus behavior. This is useful
// for the list view or other areas where we don't want to transfer
// focus to the editor canvas.
if (initialPosition === undefined || initialPosition === null) {
if (!hasMultiSelection || isMultiSelecting) {
} = multiSelectedBlockClientIds;
// Allow cross contentEditable selection by temporarily making
// all content editable. We can't rely on using the store and
// React because re-rending happens too slowly. We need to be
// able to select across instances immediately.
node.contentEditable = true;
// For some browsers, like Safari, it is important that focus
// happens BEFORE selection removal.
defaultView.getSelection().removeAllRanges();
}, [hasMultiSelection, isMultiSelecting, multiSelectedBlockClientIds, selectedBlockClientId, initialPosition, isFullSelection]);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-tab-nav.js
const container = (0,external_wp_element_namespaceObject.useRef)();
const focusCaptureBeforeRef = (0,external_wp_element_namespaceObject.useRef)();
const focusCaptureAfterRef = (0,external_wp_element_namespaceObject.useRef)();
getSelectedBlockClientId,
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = unlock((0,external_wp_data_namespaceObject.useDispatch)(store));
const isNavigationMode = (0,external_wp_data_namespaceObject.useSelect)(select => select(store).isNavigationMode(), []);
} = unlock((0,external_wp_data_namespaceObject.useSelect)(store));
// Don't allow tabbing to this element in Navigation mode.
const focusCaptureTabIndex = !isNavigationMode ? '0' : undefined;
// Reference that holds the a flag for enabling or disabling
// capturing on the focus capture elements.
const noCapture = (0,external_wp_element_namespaceObject.useRef)();
function onFocusCapture(event) {
// Do not capture incoming focus if set by us in WritingFlow.
noCapture.current = null;
} else if (hasMultiSelection()) {
container.current.focus();
} else if (getSelectedBlockClientId()) {
if (getLastFocus()?.current) {
getLastFocus().current.focus();
// Handles when the last focus has not been set yet, or has been cleared by new blocks being added via the inserter.
container.current.querySelector(`[data-block="${getSelectedBlockClientId()}"]`).focus();
const canvasElement = container.current.ownerDocument === event.target.ownerDocument ? container.current : container.current.ownerDocument.defaultView.frameElement;
// eslint-disable-next-line no-bitwise
event.target.compareDocumentPosition(canvasElement) & event.target.DOCUMENT_POSITION_FOLLOWING;
const tabbables = external_wp_dom_namespaceObject.focus.tabbable.find(container.current);
const next = isBefore ? tabbables[0] : tabbables[tabbables.length - 1];
const before = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
ref: focusCaptureBeforeRef,
tabIndex: focusCaptureTabIndex,
const after = /*#__PURE__*/(0,external_ReactJSXRuntime_namespaceObject.jsx)("div", {
ref: focusCaptureAfterRef,
tabIndex: focusCaptureTabIndex,
const ref = (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
function onKeyDown(event) {
if (event.defaultPrevented) {
if (event.keyCode === external_wp_keycodes_namespaceObject.ESCAPE && !hasMultiSelection()) {
// In Edit mode, Tab should focus the first tabbable element after
// the content, which is normally the sidebar (with block controls)
// and Shift+Tab should focus the first tabbable element before the
// content, which is normally the block toolbar.
// Arrow keys can be used, and Tab and arrow keys can be used in
// Navigation mode (press Esc), to navigate through blocks.
if (event.keyCode !== external_wp_keycodes_namespaceObject.TAB) {
const isShift = event.shiftKey;
const direction = isShift ? 'findPrevious' : 'findNext';
if (!hasMultiSelection() && !getSelectedBlockClientId()) {
// Preserve the behaviour of entering navigation mode when
// tabbing into the content without a block selection.
// `onFocusCapture` already did this previously, but we need to
// do it again here because after clearing block selection,
// focus land on the writing flow container and pressing Tab
// will no longer send focus through the focus capture element.
if (event.target === node) {
const nextTabbable = external_wp_dom_namespaceObject.focus.tabbable[direction](event.target);
// We want to constrain the tabbing to the block and its child blocks.
// If the preceding form element is within a different block,
// such as two sibling image blocks in the placeholder state,
// we want shift + tab from the first form element to move to the image
// block toolbar and not the previous image block's form element.
const currentBlock = event.target.closest('[data-block]');
const isElementPartOfSelectedBlock = currentBlock && nextTabbable && (isInSameBlock(currentBlock, nextTabbable) || isInsideRootBlock(currentBlock, nextTabbable));
// Allow tabbing from the block wrapper to a form element,
// and between form elements rendered in a block and its child blocks,
// such as inside a placeholder. Form elements are generally
// meant to be UI rather than part of the content. Ideally
// these are not rendered in the content and perhaps in the
// future they can be rendered in an iframe or shadow DOM.
if ((0,external_wp_dom_namespaceObject.isFormElement)(nextTabbable) && isElementPartOfSelectedBlock) {
const next = isShift ? focusCaptureBeforeRef : focusCaptureAfterRef;
// Disable focus capturing on the focus capture element, so it
// doesn't refocus this block and so it allows default behaviour
// (moving focus to the next tabbable element).
noCapture.current = true;
// Focusing the focus capture element, which is located above and
// below the editor, should not scroll the page all the way up or
function onFocusOut(event) {
// If focus disappears due to there being no blocks, move focus to
// the writing flow wrapper.
if (!event.relatedTarget && ownerDocument.activeElement === ownerDocument.body && getBlockCount() === 0) {
// When tabbing back to an element in block list, this event handler prevents scrolling if the
// focus capture divs (before/after) are outside of the viewport. (For example shift+tab back to a paragraph
// when focus is on a sidebar element. This prevents the scrollable writing area from jumping either to the
// top or bottom of the document.
// Note that it isn't possible to disable scrolling in the onFocus event. We need to intercept this
// earlier in the keypress handler, and call focus( { preventScroll: true } ) instead.
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus#parameters
function preventScrollOnTab(event) {
if (event.keyCode !== external_wp_keycodes_namespaceObject.TAB) {
if (event.target?.getAttribute('role') === 'region') {
if (container.current === event.target) {
const isShift = event.shiftKey;
const direction = isShift ? 'findPrevious' : 'findNext';
const target = external_wp_dom_namespaceObject.focus.tabbable[direction](event.target);
// Only do something when the next tabbable is a focus capture div (before/after)
if (target === focusCaptureBeforeRef.current || target === focusCaptureAfterRef.current) {
defaultView.addEventListener('keydown', preventScrollOnTab);
node.addEventListener('keydown', onKeyDown);
node.addEventListener('focusout', onFocusOut);
defaultView.removeEventListener('keydown', preventScrollOnTab);
node.removeEventListener('keydown', onKeyDown);
node.removeEventListener('focusout', onFocusOut);
const mergedRefs = (0,external_wp_compose_namespaceObject.useMergeRefs)([container, ref]);
return [before, mergedRefs, after];
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-arrow-nav.js
* Returns true if the element should consider edge navigation upon a keyboard
* event of the given directional key code, or false otherwise.
* @param {Element} element HTML element to test.
* @param {number} keyCode KeyboardEvent keyCode to test.
* @param {boolean} hasModifier Whether a modifier is pressed.
* @return {boolean} Whether element should consider edge navigation.
function isNavigationCandidate(element, keyCode, hasModifier) {
const isVertical = keyCode === external_wp_keycodes_namespaceObject.UP || keyCode === external_wp_keycodes_namespaceObject.DOWN;
const elementType = element.getAttribute('type');
// Native inputs should not navigate vertically, unless they are simple types that don't need up/down arrow keys.
if (isVertical && !hasModifier) {
if (tagName === 'INPUT') {
const verticalInputTypes = ['date', 'datetime-local', 'month', 'number', 'range', 'time', 'week'];
return !verticalInputTypes.includes(elementType);
// Native inputs should not navigate horizontally, unless they are simple types that don't need left/right arrow keys.
if (tagName === 'INPUT') {
const simpleInputTypes = ['button', 'checkbox', 'number', 'color', 'file', 'image', 'radio', 'reset', 'submit'];
return simpleInputTypes.includes(elementType);
// Native textareas should not navigate horizontally.
return tagName !== 'TEXTAREA';
* Returns the optimal tab target from the given focused element in the desired
* direction. A preference is made toward text fields, falling back to the block
* focus stop if no other candidates exist for the block.
* @param {Element} target Currently focused text field.
* @param {boolean} isReverse True if considering as the first field.
* @param {Element} containerElement Element containing all blocks.
* @param {boolean} onlyVertical Whether to only consider tabbable elements
* that are visually above or under the
* @return {?Element} Optimal tab target, if one exists.
function getClosestTabbable(target, isReverse, containerElement, onlyVertical) {
// Since the current focus target is not guaranteed to be a text field, find
// all focusables. Tabbability is considered later.
let focusableNodes = external_wp_dom_namespaceObject.focus.focusable.find(containerElement);
focusableNodes.reverse();
// Consider as candidates those focusables after the current target. It's
// assumed this can only be reached if the target is focusable (on its
// keydown event), so no need to verify it exists in the set.
focusableNodes = focusableNodes.slice(focusableNodes.indexOf(target) + 1);
targetRect = target.getBoundingClientRect();
function isTabCandidate(node) {
if (node.closest('[inert]')) {
// Skip if there's only one child that is content editable (and thus a
if (node.children.length === 1 && isInSameBlock(node, node.firstElementChild) && node.firstElementChild.getAttribute('contenteditable') === 'true') {
// Not a candidate if the node is not tabbable.
if (!external_wp_dom_namespaceObject.focus.tabbable.isTabbableIndex(node)) {
// Skip focusable elements such as links within content editable nodes.
if (node.isContentEditable && node.contentEditable !== 'true') {
const nodeRect = node.getBoundingClientRect();
if (nodeRect.left >= targetRect.right || nodeRect.right <= targetRect.left) {
return focusableNodes.find(isTabCandidate);
getMultiSelectedBlocksStartClientId,
getMultiSelectedBlocksEndClientId,
__unstableIsFullySelected
} = (0,external_wp_data_namespaceObject.useSelect)(store);
} = (0,external_wp_data_namespaceObject.useDispatch)(store);
return (0,external_wp_compose_namespaceObject.useRefEffect)(node => {
// Here a DOMRect is stored while moving the caret vertically so
// vertical position of the start position can be restored. This is to
// recreate browser behaviour across blocks.
function isClosestTabbableABlock(target, isReverse) {
const closestTabbable = getClosestTabbable(target, isReverse, node);
return closestTabbable && getBlockClientId(closestTabbable);
function onKeyDown(event) {
// Abort if navigation has already been handled (e.g. RichText
if (event.defaultPrevented) {
const isUp = keyCode === external_wp_keycodes_namespaceObject.UP;
const isDown = keyCode === external_wp_keycodes_namespaceObject.DOWN;
const isLeft = keyCode === external_wp_keycodes_namespaceObject.LEFT;
const isRight = keyCode === external_wp_keycodes_namespaceObject.RIGHT;
const isReverse = isUp || isLeft;
const isHorizontal = isLeft || isRight;
const isVertical = isUp || isDown;
const isNav = isHorizontal || isVertical;
const hasModifier = shiftKey || ctrlKey || altKey || metaKey;
const isNavEdge = isVertical ? external_wp_dom_namespaceObject.isVerticalEdge : external_wp_dom_namespaceObject.isHorizontalEdge;
// If there is a multi-selection, the arrow keys should collapse the
// selection to the start or end of the selection.
if (hasMultiSelection()) {
// Only handle if we have a full selection (not a native partial
if (!__unstableIsFullySelected()) {
selectBlock(getMultiSelectedBlocksStartClientId());
selectBlock(getMultiSelectedBlocksEndClientId(), -1);
// Abort if our current target is not a candidate for navigation
// (e.g. preserve native input behaviors).
if (!isNavigationCandidate(target, keyCode, hasModifier)) {
// When presing any key other than up or down, the initial vertical
// position must ALWAYS be reset. The vertical position is saved so
// it can be restored as well as possible on sebsequent vertical
// arrow key presses. It may not always be possible to restore the
// exact same position (such as at an empty line), so it wouldn't be
// good to compute the position right before any vertical arrow key
} else if (!verticalRect) {
verticalRect = (0,external_wp_dom_namespaceObject.computeCaretRect)(defaultView);
// In the case of RTL scripts, right means previous and left means
// next, which is the exact reverse of LTR.
const isReverseDir = (0,external_wp_dom_namespaceObject.isRTL)(target) ? !isReverse : isReverse;
if (isClosestTabbableABlock(target, isReverse) && isNavEdge(target, isReverse)) {
node.contentEditable = true;
// Firefox doesn't automatically move focus.
} else if (isVertical && (0,external_wp_dom_namespaceObject.isVerticalEdge)(target, isReverse) && (
// When Alt is pressed, only intercept if the caret is also at
altKey ? (0,external_wp_dom_namespaceObject.isHorizontalEdge)(target, isReverseDir) : true) && !keepCaretInsideBlock) {
const closestTabbable = getClosestTabbable(target, isReverse, node, true);
(0,external_wp_dom_namespaceObject.placeCaretAtVerticalEdge)(closestTabbable,
// When Alt is pressed, place the caret at the furthest
// horizontal edge and the furthest vertical edge.
altKey ? !isReverse : isReverse, altKey ? undefined : verticalRect);
} else if (isHorizontal && defaultView.getSelection().isCollapsed && (0,external_wp_dom_namespaceObject.isHorizontalEdge)(target, isReverseDir) && !keepCaretInsideBlock) {
const closestTabbable = getClosestTabbable(target, isReverseDir, node);
(0,external_wp_dom_namespaceObject.placeCaretAtHorizontalEdge)(closestTabbable, isReverse);
node.addEventListener('mousedown', onMouseDown);
node.addEventListener('keydown', onKeyDown);
node.removeEventListener('mousedown', onMouseDown);
node.removeEventListener('keydown', onKeyDown);
;// CONCATENATED MODULE: ./node_modules/@wordpress/block-editor/build-module/components/writing-flow/use-select-all.js