"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _clsx = _interopRequireDefault(require("clsx"));
var _icons = require("@wordpress/icons");
var _components = require("@wordpress/components");
var _data = require("@wordpress/data");
var _element = require("@wordpress/element");
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 _useBlockRefs = require("../block-list/use-block-props/use-block-refs");
var _jsxRuntime = require("react/jsx-runtime");
/**
 * External dependencies
 */

/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

/**
 * 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.
 * @param {Object} ref            Reference to the component.
 *
 * @return {Component} The component to be rendered.
 */function BlockSelectionButton({
  clientId,
  rootClientId
}, ref) {
  const selected = (0, _data.useSelect)(select => {
    const {
      getBlock,
      getBlockIndex,
      hasBlockMovingClientId,
      getBlockListSettings,
      __unstableGetEditorMode,
      getNextBlockClientId,
      getPreviousBlockClientId,
      canMoveBlock
    } = select(_store.store);
    const {
      getActiveBlockVariation,
      getBlockType
    } = select(_blocks.store);
    const index = getBlockIndex(clientId);
    const {
      name,
      attributes
    } = getBlock(clientId);
    const blockType = getBlockType(name);
    const orientation = getBlockListSettings(rootClientId)?.orientation;
    const match = getActiveBlockVariation(name, attributes);
    return {
      blockMovingMode: hasBlockMovingClientId(),
      editorMode: __unstableGetEditorMode(),
      icon: match?.icon || blockType.icon,
      label: (0, _blocks.__experimentalGetAccessibleBlockLabel)(blockType, attributes, index + 1, orientation),
      canMove: canMoveBlock(clientId, rootClientId),
      getNextBlockClientId,
      getPreviousBlockClientId
    };
  }, [clientId, rootClientId]);
  const {
    label,
    icon,
    blockMovingMode,
    editorMode,
    canMove
  } = selected;
  const {
    setNavigationMode,
    removeBlock
  } = (0, _data.useDispatch)(_store.store);

  // Focus the breadcrumb in navigation mode.
  (0, _element.useEffect)(() => {
    if (editorMode === 'navigation') {
      ref.current.focus();
      (0, _a11y.speak)(label);
    }
  }, [label, editorMode]);
  const blockElement = (0, _useBlockRefs.useBlockElement)(clientId);
  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 && !event.defaultPrevented) {
      setBlockMovingClientId(null);
      event.preventDefault();
    }
    if ((isEnter || isSpace) && startingBlockClientId) {
      const sourceRoot = getBlockRootClientId(startingBlockClientId);
      const destRoot = getBlockRootClientId(selectedBlockClientId);
      const sourceBlockIndex = getBlockIndex(startingBlockClientId);
      let destinationBlockIndex = getBlockIndex(selectedBlockClientId);
      if (sourceBlockIndex < destinationBlockIndex && sourceRoot === destRoot) {
        destinationBlockIndex -= 1;
      }
      moveBlockToPosition(startingBlockClientId, sourceRoot, destRoot, destinationBlockIndex);
      selectBlock(startingBlockClientId);
      setBlockMovingClientId(null);
    }
    // Prevent the block from being moved into itself.
    if (startingBlockClientId && selectedBlockClientId === startingBlockClientId && navigateIn) {
      return;
    }
    if (navigateDown || navigateUp || navigateOut || navigateIn) {
      if (focusedBlockUid) {
        event.preventDefault();
        selectBlock(focusedBlockUid);
      } else if (isTab && selectedBlockClientId) {
        let nextTabbable;
        if (navigateDown) {
          nextTabbable = blockElement;
          do {
            nextTabbable = _dom.focus.tabbable.findNext(nextTabbable);
          } while (nextTabbable && blockElement.contains(nextTabbable));
          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 classNames = (0, _clsx.default)('block-editor-block-list__block-selection-button', {
    'is-block-moving-mode': !!blockMovingMode
  });
  const dragHandleLabel = (0, _i18n.__)('Drag');
  const showBlockDraggable = canMove && editorMode === 'navigation';
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    className: classNames,
    children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Flex, {
      justify: "center",
      className: "block-editor-block-list__block-selection-button__content",
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockIcon.default, {
          icon: icon,
          showColors: true
        })
      }), showBlockDraggable && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockDraggable.default, {
          clientIds: [clientId],
          children: draggableProps => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button
          // TODO: Switch to `true` (40px size) if possible
          , {
            __next40pxDefaultSize: false,
            icon: _icons.dragHandle,
            className: "block-selection-button_drag-handle",
            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
          })
        })
      }), editorMode === 'navigation' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button
        // TODO: Switch to `true` (40px size) if possible
        , {
          __next40pxDefaultSize: false,
          ref: ref,
          onClick: editorMode === 'navigation' ? () => setNavigationMode(false) : undefined,
          onKeyDown: onKeyDown,
          label: label,
          showTooltip: false,
          className: "block-selection-button_select-button",
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockTitle.default, {
            clientId: clientId,
            maximumLength: 35
          })
        })
      })]
    })
  });
}
var _default = exports.default = (0, _element.forwardRef)(BlockSelectionButton);
//# sourceMappingURL=block-selection-button.js.map