UNPKG

@wordpress/block-editor

Version:
219 lines (217 loc) 7.54 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/block-editor/src/components/writing-flow/use-arrow-nav.js var use_arrow_nav_exports = {}; __export(use_arrow_nav_exports, { default: () => useArrowNav, getClosestTabbable: () => getClosestTabbable, isNavigationCandidate: () => isNavigationCandidate }); module.exports = __toCommonJS(use_arrow_nav_exports); var import_dom = require("@wordpress/dom"); var import_keycodes = require("@wordpress/keycodes"); var import_data = require("@wordpress/data"); var import_compose = require("@wordpress/compose"); var import_dom2 = require("../../utils/dom"); var import_store = require("../../store"); function isNavigationCandidate(element, keyCode, hasModifier) { const isVertical = keyCode === import_keycodes.UP || keyCode === import_keycodes.DOWN; const { tagName } = element; const elementType = element.getAttribute("type"); if (isVertical && !hasModifier) { if (tagName === "INPUT") { const verticalInputTypes = [ "date", "datetime-local", "month", "number", "range", "time", "week" ]; return !verticalInputTypes.includes(elementType); } return true; } if (tagName === "INPUT") { const simpleInputTypes = [ "button", "checkbox", "number", "color", "file", "image", "radio", "reset", "submit" ]; return simpleInputTypes.includes(elementType); } return tagName !== "TEXTAREA"; } function getClosestTabbable(target, isReverse, containerElement, onlyVertical) { let focusableNodes = import_dom.focus.focusable.find(containerElement); if (isReverse) { focusableNodes.reverse(); } focusableNodes = focusableNodes.slice( focusableNodes.indexOf(target) + 1 ); let targetRect; if (onlyVertical) { targetRect = target.getBoundingClientRect(); } function isTabCandidate(node) { if (node.closest("[inert]")) { return; } if (node.children.length === 1 && (0, import_dom2.isInSameBlock)(node, node.firstElementChild) && node.firstElementChild.getAttribute("contenteditable") === "true") { return; } if (!import_dom.focus.tabbable.isTabbableIndex(node)) { return false; } if (node.isContentEditable && node.contentEditable !== "true") { return false; } if (onlyVertical) { const nodeRect = node.getBoundingClientRect(); if (nodeRect.left >= targetRect.right || nodeRect.right <= targetRect.left) { return false; } } return true; } return focusableNodes.find(isTabCandidate); } function useArrowNav() { const { getMultiSelectedBlocksStartClientId, getMultiSelectedBlocksEndClientId, getSettings, hasMultiSelection, __unstableIsFullySelected } = (0, import_data.useSelect)(import_store.store); const { selectBlock } = (0, import_data.useDispatch)(import_store.store); return (0, import_compose.useRefEffect)((node) => { let verticalRect; function onMouseDown() { verticalRect = null; } function isClosestTabbableABlock(target, isReverse) { const closestTabbable = getClosestTabbable( target, isReverse, node ); return closestTabbable && (0, import_dom2.getBlockClientId)(closestTabbable); } function onKeyDown(event) { if (event.defaultPrevented) { return; } const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } = event; const isUp = keyCode === import_keycodes.UP; const isDown = keyCode === import_keycodes.DOWN; const isLeft = keyCode === import_keycodes.LEFT; const isRight = keyCode === import_keycodes.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 ? import_dom.isVerticalEdge : import_dom.isHorizontalEdge; const { ownerDocument } = node; const { defaultView } = ownerDocument; if (!isNav) { return; } if (hasMultiSelection()) { if (shiftKey) { return; } if (!__unstableIsFullySelected()) { return; } event.preventDefault(); if (isReverse) { selectBlock(getMultiSelectedBlocksStartClientId()); } else { selectBlock(getMultiSelectedBlocksEndClientId(), -1); } return; } if (!isNavigationCandidate(target, keyCode, hasModifier)) { return; } if (!isVertical) { verticalRect = null; } else if (!verticalRect) { verticalRect = (0, import_dom.computeCaretRect)(defaultView); } const isReverseDir = (0, import_dom.isRTL)(target) ? !isReverse : isReverse; const { keepCaretInsideBlock } = getSettings(); if (shiftKey) { if (isClosestTabbableABlock(target, isReverse) && isNavEdge(target, isReverse)) { node.contentEditable = true; node.focus(); } } else if (isVertical && (0, import_dom.isVerticalEdge)(target, isReverse) && // When Alt is pressed, only intercept if the caret is also at // the horizontal edge. (altKey ? (0, import_dom.isHorizontalEdge)(target, isReverseDir) : true) && !keepCaretInsideBlock) { const closestTabbable = getClosestTabbable( target, isReverse, node, true ); if (closestTabbable) { (0, import_dom.placeCaretAtVerticalEdge)( closestTabbable, // When Alt is pressed, place the caret at the furthest // horizontal edge and the furthest vertical edge. altKey ? !isReverse : isReverse, altKey ? void 0 : verticalRect ); event.preventDefault(); } } else if (isHorizontal && defaultView.getSelection().isCollapsed && (0, import_dom.isHorizontalEdge)(target, isReverseDir) && !keepCaretInsideBlock) { const closestTabbable = getClosestTabbable( target, isReverseDir, node ); (0, import_dom.placeCaretAtHorizontalEdge)(closestTabbable, isReverse); event.preventDefault(); } } node.addEventListener("mousedown", onMouseDown); node.addEventListener("keydown", onKeyDown); return () => { node.removeEventListener("mousedown", onMouseDown); node.removeEventListener("keydown", onKeyDown); }; }, []); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { getClosestTabbable, isNavigationCandidate }); //# sourceMappingURL=use-arrow-nav.js.map