UNPKG

@wordpress/block-editor

Version:
275 lines (227 loc) 9.17 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _element = require("@wordpress/element"); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classnames = _interopRequireDefault(require("classnames")); var _icons = require("@wordpress/icons"); var _components = require("@wordpress/components"); var _data = require("@wordpress/data"); var _keycodes = require("@wordpress/keycodes"); var _blocks = require("@wordpress/blocks"); var _a11y = require("@wordpress/a11y"); var _dom = require("@wordpress/dom"); var _i18n = require("@wordpress/i18n"); var _blockTitle = _interopRequireDefault(require("../block-title")); var _blockIcon = _interopRequireDefault(require("../block-icon")); var _store = require("../../store"); var _blockDraggable = _interopRequireDefault(require("../block-draggable")); var _useBlockDisplayInformation = _interopRequireDefault(require("../use-block-display-information")); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Returns true if the user is using windows. * * @return {boolean} Whether the user is using Windows. */ function isWindows() { return window.navigator.platform.indexOf('Win') > -1; } /** * Block selection button component, displaying the label of the block. If the block * descends from a root block, a button is displayed enabling the user to select * the root block. * * @param {string} props Component props. * @param {string} props.clientId Client ID of block. * * @return {WPComponent} The component to be rendered. */ function BlockSelectionButton({ clientId, rootClientId, blockElement }) { const blockInformation = (0, _useBlockDisplayInformation.default)(clientId); const selected = (0, _data.useSelect)(select => { var _getBlockListSettings; const { __unstableGetBlockWithoutInnerBlocks, getBlockIndex, hasBlockMovingClientId, getBlockListSettings } = select(_store.store); const index = getBlockIndex(clientId, rootClientId); const { name, attributes } = __unstableGetBlockWithoutInnerBlocks(clientId); const blockMovingMode = hasBlockMovingClientId(); return { index, name, attributes, blockMovingMode, orientation: (_getBlockListSettings = getBlockListSettings(rootClientId)) === null || _getBlockListSettings === void 0 ? void 0 : _getBlockListSettings.orientation }; }, [clientId, rootClientId]); const { index, name, attributes, blockMovingMode, orientation } = selected; const { setNavigationMode, removeBlock } = (0, _data.useDispatch)(_store.store); const ref = (0, _element.useRef)(); // Focus the breadcrumb in navigation mode. (0, _element.useEffect)(() => { ref.current.focus(); // NVDA on windows suffers from a bug where focus changes are not announced properly // See WordPress/gutenberg#24121 and nvaccess/nvda#5825 for more details // To solve it we announce the focus change manually. if (isWindows()) { (0, _a11y.speak)(label); } }, []); const { hasBlockMovingClientId, getBlockIndex, getBlockRootClientId, getClientIdsOfDescendants, getSelectedBlockClientId, getMultiSelectedBlocksEndClientId, getPreviousBlockClientId, getNextBlockClientId } = (0, _data.useSelect)(_store.store); const { selectBlock, clearSelectedBlock, setBlockMovingClientId, moveBlockToPosition } = (0, _data.useDispatch)(_store.store); function onKeyDown(event) { const { keyCode } = event; const isUp = keyCode === _keycodes.UP; const isDown = keyCode === _keycodes.DOWN; const isLeft = keyCode === _keycodes.LEFT; const isRight = keyCode === _keycodes.RIGHT; const isTab = keyCode === _keycodes.TAB; const isEscape = keyCode === _keycodes.ESCAPE; const isEnter = keyCode === _keycodes.ENTER; const isSpace = keyCode === _keycodes.SPACE; const isShift = event.shiftKey; if (keyCode === _keycodes.BACKSPACE || keyCode === _keycodes.DELETE) { removeBlock(clientId); event.preventDefault(); return; } const selectedBlockClientId = getSelectedBlockClientId(); const selectionEndClientId = getMultiSelectedBlocksEndClientId(); const selectionBeforeEndClientId = getPreviousBlockClientId(selectionEndClientId || selectedBlockClientId); const selectionAfterEndClientId = getNextBlockClientId(selectionEndClientId || selectedBlockClientId); const navigateUp = isTab && isShift || isUp; const navigateDown = isTab && !isShift || isDown; // Move out of current nesting level (no effect if at root level). const navigateOut = isLeft; // Move into next nesting level (no effect if the current block has no innerBlocks). const navigateIn = isRight; let focusedBlockUid; if (navigateUp) { focusedBlockUid = selectionBeforeEndClientId; } else if (navigateDown) { focusedBlockUid = selectionAfterEndClientId; } else if (navigateOut) { var _getBlockRootClientId; focusedBlockUid = (_getBlockRootClientId = getBlockRootClientId(selectedBlockClientId)) !== null && _getBlockRootClientId !== void 0 ? _getBlockRootClientId : selectedBlockClientId; } else if (navigateIn) { var _getClientIdsOfDescen; focusedBlockUid = (_getClientIdsOfDescen = getClientIdsOfDescendants([selectedBlockClientId])[0]) !== null && _getClientIdsOfDescen !== void 0 ? _getClientIdsOfDescen : selectedBlockClientId; } const startingBlockClientId = hasBlockMovingClientId(); if (isEscape && startingBlockClientId) { setBlockMovingClientId(null); } if ((isEnter || isSpace) && startingBlockClientId) { const sourceRoot = getBlockRootClientId(startingBlockClientId); const destRoot = getBlockRootClientId(selectedBlockClientId); const sourceBlockIndex = getBlockIndex(startingBlockClientId, sourceRoot); let destinationBlockIndex = getBlockIndex(selectedBlockClientId, destRoot); if (sourceBlockIndex < destinationBlockIndex && sourceRoot === destRoot) { destinationBlockIndex -= 1; } moveBlockToPosition(startingBlockClientId, sourceRoot, destRoot, destinationBlockIndex); selectBlock(startingBlockClientId); setBlockMovingClientId(null); } if (navigateDown || navigateUp || navigateOut || navigateIn) { if (focusedBlockUid) { event.preventDefault(); selectBlock(focusedBlockUid); } else if (isTab && selectedBlockClientId) { let nextTabbable; if (navigateDown) { nextTabbable = _dom.focus.tabbable.findNext(blockElement); if (!nextTabbable) { nextTabbable = blockElement.ownerDocument.defaultView.frameElement; nextTabbable = _dom.focus.tabbable.findNext(nextTabbable); } } else { nextTabbable = _dom.focus.tabbable.findPrevious(blockElement); } if (nextTabbable) { event.preventDefault(); nextTabbable.focus(); clearSelectedBlock(); } } } } const blockType = (0, _blocks.getBlockType)(name); const label = (0, _blocks.__experimentalGetAccessibleBlockLabel)(blockType, attributes, index + 1, orientation); const classNames = (0, _classnames.default)('block-editor-block-list__block-selection-button', { 'is-block-moving-mode': !!blockMovingMode }); const dragHandleLabel = (0, _i18n.__)('Drag'); return (0, _element.createElement)("div", { className: classNames }, (0, _element.createElement)(_components.Flex, { justify: "center", className: "block-editor-block-list__block-selection-button__content" }, (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_blockIcon.default, { icon: blockInformation === null || blockInformation === void 0 ? void 0 : blockInformation.icon, showColors: true })), (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_blockDraggable.default, { clientIds: [clientId] }, draggableProps => (0, _element.createElement)(_components.Button, (0, _extends2.default)({ icon: _icons.dragHandle, className: "block-selection-button_drag-handle", "aria-hidden": "true", label: dragHandleLabel // Should not be able to tab to drag handle as this // button can only be used with a pointer device. , tabIndex: "-1" }, draggableProps)))), (0, _element.createElement)(_components.FlexItem, null, (0, _element.createElement)(_components.Button, { ref: ref, onClick: () => setNavigationMode(false), onKeyDown: onKeyDown, label: label, className: "block-selection-button_select-button" }, (0, _element.createElement)(_blockTitle.default, { clientId: clientId }))))); } var _default = BlockSelectionButton; exports.default = _default; //# sourceMappingURL=block-selection-button.js.map