"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = BlockTools;
var _data = require("@wordpress/data");
var _dom = require("@wordpress/dom");
var _components = require("@wordpress/components");
var _keyboardShortcuts = require("@wordpress/keyboard-shortcuts");
var _element = require("@wordpress/element");
var _blocks = require("@wordpress/blocks");
var _a11y = require("@wordpress/a11y");
var _i18n = require("@wordpress/i18n");
var _emptyBlockInserter = _interopRequireDefault(require("./empty-block-inserter"));
var _insertionPoint = _interopRequireWildcard(require("./insertion-point"));
var _blockToolbarPopover = _interopRequireDefault(require("./block-toolbar-popover"));
var _blockToolbarBreadcrumb = _interopRequireDefault(require("./block-toolbar-breadcrumb"));
var _store = require("../../store");
var _usePopoverScroll = _interopRequireDefault(require("../block-popover/use-popover-scroll"));
var _zoomOutModeInserters = _interopRequireDefault(require("./zoom-out-mode-inserters"));
var _useShowBlockTools = require("./use-show-block-tools");
var _lockUnlock = require("../../lock-unlock");
var _getEditorRegion = _interopRequireDefault(require("../../utils/get-editor-region"));
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

function selector(select) {
  const {
    getSelectedBlockClientId,
    getFirstMultiSelectedBlockClientId,
    getSettings,
    __unstableGetEditorMode,
    isTyping
  } = select(_store.store);
  const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId();
  const editorMode = __unstableGetEditorMode();
  return {
    clientId,
    hasFixedToolbar: getSettings().hasFixedToolbar,
    isTyping: isTyping(),
    isZoomOutMode: editorMode === 'zoom-out'
  };
}

/**
 * Renders block tools (the block toolbar, select/navigation mode toolbar, the
 * insertion point and a slot for the inline rich text toolbar). Must be wrapped
 * around the block content and editor styles wrapper or iframe.
 *
 * @param {Object} $0                      Props.
 * @param {Object} $0.children             The block content and style container.
 * @param {Object} $0.__unstableContentRef Ref holding the content scroll container.
 */
function BlockTools({
  children,
  __unstableContentRef,
  ...props
}) {
  const {
    clientId,
    hasFixedToolbar,
    isTyping,
    isZoomOutMode
  } = (0, _data.useSelect)(selector, []);
  const isMatch = (0, _keyboardShortcuts.__unstableUseShortcutEventMatch)();
  const {
    getBlocksByClientId,
    getSelectedBlockClientIds,
    getBlockRootClientId,
    isGroupable
  } = (0, _data.useSelect)(_store.store);
  const {
    getGroupingBlockName
  } = (0, _data.useSelect)(_blocks.store);
  const {
    showEmptyBlockSideInserter,
    showBreadcrumb,
    showBlockToolbarPopover
  } = (0, _useShowBlockTools.useShowBlockTools)();
  const {
    clearSelectedBlock,
    duplicateBlocks,
    removeBlocks,
    replaceBlocks,
    insertAfterBlock,
    insertBeforeBlock,
    selectBlock,
    moveBlocksUp,
    moveBlocksDown,
    expandBlock
  } = (0, _lockUnlock.unlock)((0, _data.useDispatch)(_store.store));
  const blockSelectionButtonRef = (0, _element.useRef)();
  function onKeyDown(event) {
    if (event.defaultPrevented) {
      return;
    }
    if (isMatch('core/block-editor/move-up', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        const rootClientId = getBlockRootClientId(clientIds[0]);
        moveBlocksUp(clientIds, rootClientId);
      }
    } else if (isMatch('core/block-editor/move-down', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        const rootClientId = getBlockRootClientId(clientIds[0]);
        moveBlocksDown(clientIds, rootClientId);
      }
    } else if (isMatch('core/block-editor/duplicate', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        duplicateBlocks(clientIds);
      }
    } else if (isMatch('core/block-editor/remove', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        removeBlocks(clientIds);
      }
    } else if (isMatch('core/block-editor/insert-after', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        insertAfterBlock(clientIds[clientIds.length - 1]);
      }
    } else if (isMatch('core/block-editor/insert-before', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length) {
        event.preventDefault();
        insertBeforeBlock(clientIds[0]);
      }
    } else if (isMatch('core/block-editor/unselect', event)) {
      if (event.target.closest('[role=toolbar]')) {
        // This shouldn't be necessary, but we have a combination of a few things all combining to create a situation where:
        // - Because the block toolbar uses createPortal to populate the block toolbar fills, we can't rely on the React event bubbling to hit the onKeyDown listener for the block toolbar
        // - Since we can't use the React tree, we use the DOM tree which _should_ handle the event bubbling correctly from a `createPortal` element.
        // - This bubbles via the React tree, which hits this `unselect` escape keypress before the block toolbar DOM event listener has access to it.
        // An alternative would be to remove the addEventListener on the navigableToolbar and use this event to handle it directly right here. That feels hacky too though.
        return;
      }
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length > 1) {
        event.preventDefault();
        // If there is more than one block selected, select the first
        // block so that focus is directed back to the beginning of the selection.
        // In effect, to the user this feels like deselecting the multi-selection.
        selectBlock(clientIds[0]);
      } else if (clientIds.length === 1 && event.target === blockSelectionButtonRef?.current) {
        event.preventDefault();
        clearSelectedBlock();
        (0, _getEditorRegion.default)(__unstableContentRef.current)?.focus();
      }
    } else if (isMatch('core/block-editor/collapse-list-view', event)) {
      // If focus is currently within a text field, such as a rich text block or other editable field,
      // skip collapsing the list view, and allow the keyboard shortcut to be handled by the text field.
      // This condition checks for both the active element and the active element within an iframed editor.
      if ((0, _dom.isTextField)(event.target) || (0, _dom.isTextField)(event.target?.contentWindow?.document?.activeElement)) {
        return;
      }
      event.preventDefault();
      expandBlock(clientId);
    } else if (isMatch('core/block-editor/group', event)) {
      const clientIds = getSelectedBlockClientIds();
      if (clientIds.length > 1 && isGroupable(clientIds)) {
        event.preventDefault();
        const blocks = getBlocksByClientId(clientIds);
        const groupingBlockName = getGroupingBlockName();
        const newBlocks = (0, _blocks.switchToBlockType)(blocks, groupingBlockName);
        replaceBlocks(clientIds, newBlocks);
        (0, _a11y.speak)((0, _i18n.__)('Selected blocks are grouped.'));
      }
    }
  }
  const blockToolbarRef = (0, _usePopoverScroll.default)(__unstableContentRef);
  const blockToolbarAfterRef = (0, _usePopoverScroll.default)(__unstableContentRef);
  return (
    /*#__PURE__*/
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
    (0, _jsxRuntime.jsx)("div", {
      ...props,
      onKeyDown: onKeyDown,
      children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_insertionPoint.InsertionPointOpenRef.Provider, {
        value: (0, _element.useRef)(false),
        children: [!isTyping && !isZoomOutMode && /*#__PURE__*/(0, _jsxRuntime.jsx)(_insertionPoint.default, {
          __unstableContentRef: __unstableContentRef
        }), showEmptyBlockSideInserter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_emptyBlockInserter.default, {
          __unstableContentRef: __unstableContentRef,
          clientId: clientId
        }), showBlockToolbarPopover && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockToolbarPopover.default, {
          __unstableContentRef: __unstableContentRef,
          clientId: clientId,
          isTyping: isTyping
        }), showBreadcrumb && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockToolbarBreadcrumb.default, {
          ref: blockSelectionButtonRef,
          __unstableContentRef: __unstableContentRef,
          clientId: clientId
        }), !isZoomOutMode && !hasFixedToolbar && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Popover.Slot, {
          name: "block-toolbar",
          ref: blockToolbarRef
        }), children, /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Popover.Slot, {
          name: "__unstable-block-tools-after",
          ref: blockToolbarAfterRef
        }), isZoomOutMode && /*#__PURE__*/(0, _jsxRuntime.jsx)(_zoomOutModeInserters.default, {
          __unstableContentRef: __unstableContentRef
        })]
      })
    })
  );
}
//# sourceMappingURL=index.js.map