/**
 * WordPress dependencies
 */
import { useSelect, useDispatch } from '@wordpress/data';
import { isTextField } from '@wordpress/dom';
import { Popover } from '@wordpress/components';
import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
import { switchToBlockType, store as blocksStore } from '@wordpress/blocks';
import { speak } from '@wordpress/a11y';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import EmptyBlockInserter from './empty-block-inserter';
import { InsertionPointOpenRef, default as InsertionPoint } from './insertion-point';
import BlockToolbarPopover from './block-toolbar-popover';
import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb';
import ZoomOutPopover from './zoom-out-popover';
import { store as blockEditorStore } from '../../store';
import usePopoverScroll from '../block-popover/use-popover-scroll';
import ZoomOutModeInserters from './zoom-out-mode-inserters';
import { useShowBlockTools } from './use-show-block-tools';
import { unlock } from '../../lock-unlock';
import getEditorRegion from '../../utils/get-editor-region';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
function selector(select) {
  const {
    getSelectedBlockClientId,
    getFirstMultiSelectedBlockClientId,
    getSettings,
    __unstableGetEditorMode,
    isTyping
  } = select(blockEditorStore);
  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.
 */
export default function BlockTools({
  children,
  __unstableContentRef,
  ...props
}) {
  const {
    clientId,
    hasFixedToolbar,
    isTyping,
    isZoomOutMode
  } = useSelect(selector, []);
  const isMatch = useShortcutEventMatch();
  const {
    getBlocksByClientId,
    getSelectedBlockClientIds,
    getBlockRootClientId,
    isGroupable
  } = useSelect(blockEditorStore);
  const {
    getGroupingBlockName
  } = useSelect(blocksStore);
  const {
    showEmptyBlockSideInserter,
    showBreadcrumb,
    showBlockToolbarPopover,
    showZoomOutToolbar
  } = useShowBlockTools();
  const {
    clearSelectedBlock,
    duplicateBlocks,
    removeBlocks,
    replaceBlocks,
    insertAfterBlock,
    insertBeforeBlock,
    selectBlock,
    moveBlocksUp,
    moveBlocksDown,
    expandBlock
  } = unlock(useDispatch(blockEditorStore));
  const blockSelectionButtonRef = 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();
        getEditorRegion(__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 (isTextField(event.target) || 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 = switchToBlockType(blocks, groupingBlockName);
        replaceBlocks(clientIds, newBlocks);
        speak(__('Selected blocks are grouped.'));
      }
    }
  }
  const blockToolbarRef = usePopoverScroll(__unstableContentRef);
  const blockToolbarAfterRef = usePopoverScroll(__unstableContentRef);
  return (
    /*#__PURE__*/
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
    _jsx("div", {
      ...props,
      onKeyDown: onKeyDown,
      children: /*#__PURE__*/_jsxs(InsertionPointOpenRef.Provider, {
        value: useRef(false),
        children: [!isTyping && /*#__PURE__*/_jsx(InsertionPoint, {
          __unstableContentRef: __unstableContentRef
        }), showEmptyBlockSideInserter && /*#__PURE__*/_jsx(EmptyBlockInserter, {
          __unstableContentRef: __unstableContentRef,
          clientId: clientId
        }), showBlockToolbarPopover && /*#__PURE__*/_jsx(BlockToolbarPopover, {
          __unstableContentRef: __unstableContentRef,
          clientId: clientId,
          isTyping: isTyping
        }), showBreadcrumb && /*#__PURE__*/_jsx(BlockToolbarBreadcrumb, {
          ref: blockSelectionButtonRef,
          __unstableContentRef: __unstableContentRef,
          clientId: clientId
        }), showZoomOutToolbar && /*#__PURE__*/_jsx(ZoomOutPopover, {
          __unstableContentRef: __unstableContentRef,
          clientId: clientId
        }), !isZoomOutMode && !hasFixedToolbar && /*#__PURE__*/_jsx(Popover.Slot, {
          name: "block-toolbar",
          ref: blockToolbarRef
        }), children, /*#__PURE__*/_jsx(Popover.Slot, {
          name: "__unstable-block-tools-after",
          ref: blockToolbarAfterRef
        }), window.__experimentalEnableZoomedOutPatternsTab && isZoomOutMode && /*#__PURE__*/_jsx(ZoomOutModeInserters, {
          __unstableContentRef: __unstableContentRef
        })]
      })
    })
  );
}
//# sourceMappingURL=index.js.map