{
( { onDraggableStart, onDraggableEnd } ) => {
@@ -31,11 +53,4 @@ const BlockDraggable = ( { children, clientId, rootClientId, blockElementId, ind
);
};
-export default withSelect( ( select, { clientId } ) => {
- const { getBlockIndex, getBlockRootClientId } = select( 'core/block-editor' );
- const rootClientId = getBlockRootClientId( clientId );
- return {
- index: getBlockIndex( clientId, rootClientId ),
- rootClientId,
- };
-} )( BlockDraggable );
+export default BlockDraggable;
diff --git a/packages/block-editor/src/components/block-list/block-mobile-toolbar.js b/packages/block-editor/src/components/block-list/block-mobile-toolbar.js
deleted file mode 100644
index 8af64ec12c021..0000000000000
--- a/packages/block-editor/src/components/block-list/block-mobile-toolbar.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { ifViewportMatches } from '@wordpress/viewport';
-
-/**
- * Internal dependencies
- */
-import BlockMover from '../block-mover';
-import VisualEditorInserter from '../inserter';
-
-function BlockMobileToolbar( { clientId, moverDirection } ) {
- return (
-
-
-
-
- );
-}
-
-export default ifViewportMatches( '< small' )( BlockMobileToolbar );
diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js
index 48b5506e452f2..24413ee9011b1 100644
--- a/packages/block-editor/src/components/block-list/block.js
+++ b/packages/block-editor/src/components/block-list/block.js
@@ -35,7 +35,6 @@ import { compose, pure, ifCondition } from '@wordpress/compose';
* Internal dependencies
*/
import BlockEdit from '../block-edit';
-import BlockMover from '../block-mover';
import BlockDropZone from '../block-drop-zone';
import BlockInvalidWarning from './block-invalid-warning';
import BlockCrashWarning from './block-crash-warning';
@@ -43,8 +42,6 @@ import BlockCrashBoundary from './block-crash-boundary';
import BlockHtml from './block-html';
import BlockBreadcrumb from './breadcrumb';
import BlockContextualToolbar from './block-contextual-toolbar';
-import BlockMultiControls from './multi-controls';
-import BlockMobileToolbar from './block-mobile-toolbar';
import BlockInsertionPoint from './insertion-point';
import IgnoreNestedEvents from '../ignore-nested-events';
import InserterWithShortcuts from '../inserter-with-shortcuts';
@@ -75,11 +72,10 @@ function BlockListBlock( {
isPartOfMultiSelection,
isFirstMultiSelected,
isTypingWithinBlock,
+ isDragging,
isCaretWithinFormattedText,
isEmptyDefaultBlock,
- isMovable,
isParentOfSelectedBlock,
- isDraggable,
isSelectionEnabled,
className,
name,
@@ -171,15 +167,6 @@ function BlockListBlock( {
}
} );
- // Handling the dragging state
- const [ isDragging, setBlockDraggingState ] = useState( false );
- const onDragStart = () => {
- setBlockDraggingState( true );
- };
- const onDragEnd = () => {
- setBlockDraggingState( false );
- };
-
// Handling the error state
const [ hasError, setErrorState ] = useState( false );
const onBlockError = () => setErrorState( true );
@@ -397,13 +384,6 @@ function BlockListBlock( {
! hasFixedToolbar &&
isHovered &&
! isEmptyDefaultBlock;
- // We render block movers and block settings to keep them tabbale even if hidden
- const shouldRenderMovers =
- ! isNavigationMode &&
- isSelected &&
- ! showEmptyBlockSideInserter &&
- ! isPartOfMultiSelection &&
- ! isTypingWithinBlock;
const shouldShowBreadcrumb =
( isSelected && isNavigationMode ) ||
( ! isNavigationMode && ! isFocusMode && isHovered && ! isEmptyDefaultBlock );
@@ -415,7 +395,6 @@ function BlockListBlock( {
( isSelected && ( ! isTypingWithinBlock || isCaretWithinFormattedText ) ) ||
isFirstMultiSelected
);
- const shouldShowMobileToolbar = ! isNavigationMode && shouldAppearSelected;
// Insertion point can only be made visible if the block is at the
// the extent of a multi-selection, or not in a multi-selection.
@@ -451,20 +430,6 @@ function BlockListBlock( {
};
}
const blockElementId = `block-${ clientId }`;
- const blockMover = (
-
- );
// We wrap the BlockEdit component in a div that hides it when editing in
// HTML mode. This allows us to render all of the ancillary pieces
@@ -525,19 +490,12 @@ function BlockListBlock( {
clientId={ clientId }
rootClientId={ rootClientId }
/>
- { isFirstMultiSelected && (
-
- ) }
- { shouldRenderMovers && ( moverDirection === 'vertical' ) && blockMover }
{ shouldShowBreadcrumb && (
) }
- { shouldRenderMovers && ( moverDirection === 'horizontal' ) && blockMover }
{ ! isValid && [
{ !! hasError && }
- { shouldShowMobileToolbar && (
-
- ) }
{ showInserterShortcuts && (
@@ -625,6 +579,7 @@ const applyWithSelect = withSelect(
isBlockMultiSelected,
isFirstMultiSelectedBlock,
isTyping,
+ isDraggingBlocks,
isCaretWithinFormattedText,
getBlockMode,
isSelectionEnabled,
@@ -644,6 +599,7 @@ const applyWithSelect = withSelect(
const isParentOfSelectedBlock = hasSelectedInnerBlock( clientId, true );
const index = getBlockIndex( clientId, rootClientId );
const blockOrder = getBlockOrder( rootClientId );
+ const isPartOfMultiSelection = isBlockMultiSelected( clientId ) || isAncestorMultiSelected( clientId );
// The fallback to `{}` is a temporary fix.
// This function should never be called when a block is not present in the state.
@@ -651,8 +607,7 @@ const applyWithSelect = withSelect(
const { name, attributes, isValid } = block || {};
return {
- isPartOfMultiSelection:
- isBlockMultiSelected( clientId ) || isAncestorMultiSelected( clientId ),
+ isDragging: isDraggingBlocks() && ( isSelected || isPartOfMultiSelection ),
isFirstMultiSelected: isFirstMultiSelectedBlock( clientId ),
// We only care about this prop when the block is selected
// Thus to avoid unnecessary rerenders we avoid updating the prop if the block is not selected.
@@ -664,12 +619,12 @@ const applyWithSelect = withSelect(
initialPosition: isSelected ? getSelectedBlocksInitialCaretPosition() : null,
isEmptyDefaultBlock:
name && isUnmodifiedDefaultBlock( { name, attributes } ),
- isMovable: 'all' !== templateLock,
isLocked: !! templateLock,
isFocusMode: focusMode && isLargeViewport,
hasFixedToolbar: hasFixedToolbar && isLargeViewport,
isLast: index === blockOrder.length - 1,
isNavigationMode: isNavigationMode(),
+ isPartOfMultiSelection,
isRTL,
// Users of the editor.BlockListBlock filter used to be able to access the block prop
diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js
index 54511ac941ecc..ed7334f5d84c6 100644
--- a/packages/block-editor/src/components/block-list/index.js
+++ b/packages/block-editor/src/components/block-list/index.js
@@ -196,7 +196,6 @@ class BlockList extends Component {
blockClientIds,
rootClientId,
__experimentalMoverDirection: moverDirection = 'vertical',
- isDraggable,
selectedBlockClientId,
multiSelectedBlockClientIds,
hasMultiSelection,
@@ -227,7 +226,6 @@ class BlockList extends Component {
clientId={ clientId }
blockRef={ this.setBlockRef }
onSelectionStart={ this.onSelectionStart }
- isDraggable={ isDraggable }
moverDirection={ moverDirection }
// This prop is explicitely computed and passed down
diff --git a/packages/block-editor/src/components/block-list/multi-controls.js b/packages/block-editor/src/components/block-list/multi-controls.js
deleted file mode 100644
index 2f49ca2ca0a3b..0000000000000
--- a/packages/block-editor/src/components/block-list/multi-controls.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { withSelect } from '@wordpress/data';
-
-/**
- * Internal dependencies
- */
-import BlockMover from '../block-mover';
-
-function BlockListMultiControls( {
- multiSelectedBlockClientIds,
- isSelecting,
- moverDirection,
-} ) {
- if ( isSelecting ) {
- return null;
- }
-
- return (
-
- );
-}
-
-export default withSelect( ( select ) => {
- const {
- getMultiSelectedBlockClientIds,
- isMultiSelecting,
- } = select( 'core/block-editor' );
- const clientIds = getMultiSelectedBlockClientIds();
-
- return {
- multiSelectedBlockClientIds: clientIds,
- isSelecting: isMultiSelecting(),
- };
-} )( BlockListMultiControls );
diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss
index e40b7676be37c..22880eaa8108a 100644
--- a/packages/block-editor/src/components/block-list/style.scss
+++ b/packages/block-editor/src/components/block-list/style.scss
@@ -661,82 +661,6 @@
}
}
-
-/**
- * Mobile unified toolbar.
- */
-
-.block-editor-block-list__block {
-
- // Show side UI inline below the block on mobile.
- .block-editor-block-list__block-mobile-toolbar {
- display: flex;
- flex-direction: row;
-
- // Make room for the height of the block toolbar above.
- transform: translateY($block-padding + $border-width);
- margin-top: $block-toolbar-height;
- margin-right: -$block-padding;
- margin-left: -$block-padding;
- border-top: $border-width solid $light-gray-800;
- height: $block-toolbar-height;
-
- @include break-small() {
- display: none;
- }
-
- // Add a white background to prevent the block's left border from showing through.
- background-color: $white;
-
- // Show a shadow below the selected block to imply separation.
- box-shadow: $shadow-below-only;
- @include break-small() {
- box-shadow: none;
- }
-
- // Movers, inserter, trash, and ellipsis.
- .block-editor-inserter {
- position: relative;
- left: auto;
- top: auto;
- margin: 0;
- }
-
- .block-editor-inserter__toggle,
- .block-editor-block-mover__control {
- width: $icon-button-size;
- height: $icon-button-size;
- border-radius: $radius-round-rectangle;
- padding: 3px;
- margin: 0;
- justify-content: center;
- align-items: center;
-
- .dashicon {
- margin: auto;
- }
- }
-
- // Movers
- .block-editor-block-mover {
- display: flex;
- margin-right: auto;
-
- .block-editor-inserter,
- .block-editor-block-mover__control {
- float: left;
- }
- }
- }
-
- // Reset negative margins on mobile for full-width.
- &[data-align="full"] .block-editor-block-list__block-mobile-toolbar {
- margin-left: 0;
- margin-right: 0;
- }
-}
-
-
/**
* In-Canvas Inserter
*/
@@ -874,12 +798,13 @@
// Position toolbar below the block on mobile.
position: absolute;
- bottom: $block-toolbar-height - $block-padding - $border-width;
+ bottom: - $block-toolbar-height - $block-padding - $border-width;
left: -$block-padding;
right: -$block-padding;
// Paint the borders on the toolbar itself on mobile.
border-top: $border-width solid $light-gray-800;
+ border-bottom: $border-width solid $light-gray-800;
.components-toolbar {
border-top: none;
border-bottom: none;
@@ -887,6 +812,7 @@
@include break-small() {
border-top: none;
+ border-bottom: none;
.components-toolbar {
border-top: $border-width solid $light-gray-800;
border-bottom: $border-width solid $light-gray-800;
diff --git a/packages/block-editor/src/components/block-mover/drag-handle.js b/packages/block-editor/src/components/block-mover/drag-handle.js
index 86551bf4be0e3..097d83ba12e72 100644
--- a/packages/block-editor/src/components/block-mover/drag-handle.js
+++ b/packages/block-editor/src/components/block-mover/drag-handle.js
@@ -3,36 +3,32 @@
*/
import classnames from 'classnames';
+/**
+ * WordPress dependencies
+ */
+import { IconButton } from '@wordpress/components';
+
/**
* Internal dependencies
*/
import BlockDraggable from '../block-draggable';
+import { dragHandle } from './icons';
-export const IconDragHandle = ( { isVisible, className, icon, onDragStart, onDragEnd, blockElementId, clientId } ) => {
- if ( ! isVisible ) {
- return null;
- }
-
+export const IconDragHandle = ( { className, clientIds } ) => {
const dragHandleClassNames = classnames( 'editor-block-mover__control-drag-handle block-editor-block-mover__control-drag-handle', className );
return (
-
+
{
( { onDraggableStart, onDraggableEnd } ) => (
-
- { icon }
-
+ />
) }
);
diff --git a/packages/block-editor/src/components/block-mover/index.js b/packages/block-editor/src/components/block-mover/index.js
index cd1f4483eceb1..d5ab025d6e657 100644
--- a/packages/block-editor/src/components/block-mover/index.js
+++ b/packages/block-editor/src/components/block-mover/index.js
@@ -1,14 +1,14 @@
/**
* External dependencies
*/
-import { first, last, partial, castArray } from 'lodash';
+import { first, last, partial } from 'lodash';
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
-import { IconButton } from '@wordpress/components';
+import { IconButton, Toolbar } from '@wordpress/components';
import { getBlockType } from '@wordpress/blocks';
import { Component } from '@wordpress/element';
import { withSelect, withDispatch } from '@wordpress/data';
@@ -18,7 +18,7 @@ import { withInstanceId, compose } from '@wordpress/compose';
* Internal dependencies
*/
import { getBlockMoverDescription } from './mover-description';
-import { leftArrow, rightArrow, upArrow, downArrow, dragHandle } from './icons';
+import { leftArrow, rightArrow, upArrow, downArrow } from './icons';
import { IconDragHandle } from './drag-handle';
export class BlockMover extends Component {
@@ -44,9 +44,9 @@ export class BlockMover extends Component {
}
render() {
- const { onMoveUp, onMoveDown, __experimentalOrientation: orientation, isRTL, isFirst, isLast, isDraggable, onDragStart, onDragEnd, clientIds, blockElementId, blockType, firstIndex, isLocked, instanceId, isHidden, rootClientId } = this.props;
+ const { onMoveUp, onMoveDown, __experimentalOrientation: orientation, isRTL, isFirst, isLast, clientIds, blockType, firstIndex, isLocked, instanceId, isHidden, rootClientId } = this.props;
const { isFocused } = this.state;
- const blocksCount = castArray( clientIds ).length;
+ const blocksCount = clientIds.length;
if ( isLocked || ( isFirst && isLast && ! rootClientId ) ) {
return null;
}
@@ -86,7 +86,7 @@ export class BlockMover extends Component {
// to an unfocused state (body as active element) without firing blur on,
// the rendering parent, leaving it unable to react to focus out.
return (
-
+
-
+
);
}
}
@@ -154,13 +149,12 @@ export class BlockMover extends Component {
export default compose(
withSelect( ( select, { clientIds } ) => {
const { getBlock, getBlockIndex, getTemplateLock, getBlockRootClientId, getBlockOrder } = select( 'core/block-editor' );
- const normalizedClientIds = castArray( clientIds );
- const firstClientId = first( normalizedClientIds );
+ const firstClientId = first( clientIds );
const block = getBlock( firstClientId );
- const rootClientId = getBlockRootClientId( first( normalizedClientIds ) );
+ const rootClientId = getBlockRootClientId( first( clientIds ) );
const blockOrder = getBlockOrder( rootClientId );
const firstIndex = getBlockIndex( firstClientId, rootClientId );
- const lastIndex = getBlockIndex( last( normalizedClientIds ), rootClientId );
+ const lastIndex = getBlockIndex( last( clientIds ), rootClientId );
const { getSettings } = select( 'core/block-editor' );
const {
isRTL,
diff --git a/packages/block-editor/src/components/block-mover/style.scss b/packages/block-editor/src/components/block-mover/style.scss
index 61493ee98b4f0..33b4d13332030 100644
--- a/packages/block-editor/src/components/block-mover/style.scss
+++ b/packages/block-editor/src/components/block-mover/style.scss
@@ -1,96 +1,3 @@
-.block-editor-block-mover {
- @include break-small() {
- opacity: 0;
- background: $white;
- border: 1px solid $dark-opacity-light-800;
- border-radius: $radius-round-rectangle;
- transition: box-shadow 0.2s ease-out;
- @include reduce-motion("transition");
-
- &.is-visible {
- @include edit-post__fade-in-animation;
- }
-
- &:hover {
- box-shadow: $shadow-toolbar;
- }
-
- // 24px is the smallest size of a good pressable button.
- // With 3 pieces of side UI, that comes to a total of 72px.
- // To vertically center against a 56px paragraph, move upwards 72px - 56px / 2.
- margin-top: -$grid-size;
- }
-
- &.is-horizontal {
- margin-top: 5px; // The height of the appender is 36px. This pushes down the mover to be centered according to that.
- margin-right: $grid-size;
- padding-right: 0;
- min-height: auto;
- width: ($icon-button-size-small * 2) + ($border-width * 2);
- height: $icon-button-size-small + ($border-width * 2);
- display: flex;
-
- .block-editor-block-mover__control {
- width: $icon-button-size-small;
- height: $icon-button-size-small;
-
- svg {
- width: $icon-button-size-small;
- padding: 3px;
- }
- }
- }
-}
-
-// Don't add negative vertical margin for wide, fullwide, or mobile.
-// @todo: simplify this selector.
-@include break-small() {
- .block-editor-block-list__block:not([data-align="wide"]):not([data-align="full"]) .editor-block-mover:not(.is-horizontal) {
- margin-top: 0;
- }
-}
-
-// Mover icon buttons.
-.block-editor-block-mover__control {
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- padding: 0;
- border: none;
- box-shadow: none;
-
- // Carefully adjust the size of the side UI to fit one paragraph of text (56px).
- width: $block-side-ui-width;
- height: $icon-button-size-small;
-
- svg {
- width: $block-side-ui-width;
- height: $icon-button-size-small;
- padding: #{ ($block-side-ui-width - $icon-button-size-small) / 2 } #{ ($block-side-ui-width - 18px) / 2 }; // This makes the SVG fill the whole available area, without scaling the artwork.
- }
-
- &[aria-disabled="true"] {
- cursor: default;
- pointer-events: none;
- color: $dark-opacity-300;
- }
-
- @include break-small() {
- color: $dark-opacity-300;
-
- &:not(:disabled):not([aria-disabled="true"]):not(.is-default):hover {
- background-color: transparent;
- box-shadow: none;
- }
-
- &:focus:not(:disabled) {
- background-color: transparent;
- }
- }
-
-}
-
.block-editor-block-mover__control-drag-handle {
cursor: move; // Fallback for IE/Edge < 14
cursor: grab;
diff --git a/packages/block-editor/src/components/block-switcher/multi-blocks-switcher.js b/packages/block-editor/src/components/block-switcher/multi-blocks-switcher.js
deleted file mode 100644
index 8adae420dab99..0000000000000
--- a/packages/block-editor/src/components/block-switcher/multi-blocks-switcher.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { withSelect } from '@wordpress/data';
-
-/**
- * Internal dependencies
- */
-import BlockSwitcher from './';
-
-export function MultiBlocksSwitcher( { isMultiBlockSelection, selectedBlockClientIds } ) {
- if ( ! isMultiBlockSelection ) {
- return null;
- }
- return (
-
- );
-}
-
-export default withSelect(
- ( select ) => {
- const selectedBlockClientIds = select( 'core/block-editor' ).getMultiSelectedBlockClientIds();
- return {
- isMultiBlockSelection: selectedBlockClientIds.length > 1,
- selectedBlockClientIds,
- };
- }
-)( MultiBlocksSwitcher );
diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js
index 83edd7814a0ed..4aa39c5364270 100644
--- a/packages/block-editor/src/components/block-toolbar/index.js
+++ b/packages/block-editor/src/components/block-toolbar/index.js
@@ -1,56 +1,54 @@
/**
* WordPress dependencies
*/
-import { withSelect } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
/**
* Internal dependencies
*/
+import BlockMover from '../block-mover';
import BlockSwitcher from '../block-switcher';
-import MultiBlocksSwitcher from '../block-switcher/multi-blocks-switcher';
import BlockControls from '../block-controls';
import BlockFormatControls from '../block-format-controls';
import BlockSettingsMenu from '../block-settings-menu';
-function BlockToolbar( { blockClientIds, isValid, mode } ) {
- if ( blockClientIds.length === 0 ) {
- return null;
- }
+function BlockToolbar( { moverDirection } ) {
+ const { blockIds, isValid, mode } = useSelect( ( select ) => {
+ const {
+ getBlockMode,
+ getSelectedBlockClientIds,
+ isBlockValid,
+ } = select( 'core/block-editor' );
+ const blockClientIds = getSelectedBlockClientIds();
+ return {
+ blockIds: blockClientIds,
+ isValid: blockClientIds.length === 1 ? isBlockValid( blockClientIds[ 0 ] ) : null,
+ mode: blockClientIds.length === 1 ? getBlockMode( blockClientIds[ 0 ] ) : null,
+ };
+ } );
- if ( blockClientIds.length > 1 ) {
- return (
-
-
-
-
- );
+ if ( blockIds.length === 0 ) {
+ return null;
}
+ const shouldShowVisualToolbar = isValid && mode === 'visual';
+ const isMultiToolbar = blockIds.length > 1;
return (
- { mode === 'visual' && isValid && (
+
+ { ( shouldShowVisualToolbar || isMultiToolbar ) && }
+ { shouldShowVisualToolbar && ! isMultiToolbar && (
<>
-
>
) }
-
+
);
}
-export default withSelect( ( select ) => {
- const {
- getBlockMode,
- getSelectedBlockClientIds,
- isBlockValid,
- } = select( 'core/block-editor' );
- const blockClientIds = getSelectedBlockClientIds();
-
- return {
- blockClientIds,
- isValid: blockClientIds.length === 1 ? isBlockValid( blockClientIds[ 0 ] ) : null,
- mode: blockClientIds.length === 1 ? getBlockMode( blockClientIds[ 0 ] ) : null,
- };
-} )( BlockToolbar );
+export default BlockToolbar;
diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js
index c7792608518ac..2073d08d9cb3b 100644
--- a/packages/block-editor/src/components/index.js
+++ b/packages/block-editor/src/components/index.js
@@ -63,7 +63,6 @@ export { default as BlockToolbar } from './block-toolbar';
export { default as CopyHandler } from './copy-handler';
export { default as DefaultBlockAppender } from './default-block-appender';
export { default as Inserter } from './inserter';
-export { default as MultiBlocksSwitcher } from './block-switcher/multi-blocks-switcher';
export { default as MultiSelectScrollIntoView } from './multi-select-scroll-into-view';
export { default as NavigableToolbar } from './navigable-toolbar';
export { default as ObserveTyping } from './observe-typing';
diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js
index a7956c70e0d21..18b54cf22573b 100644
--- a/packages/block-editor/src/store/actions.js
+++ b/packages/block-editor/src/store/actions.js
@@ -652,6 +652,28 @@ export function stopTyping() {
};
}
+/**
+ * Returns an action object used in signalling that the user has begun to drag blocks.
+ *
+ * @return {Object} Action object.
+ */
+export function startDraggingBlocks() {
+ return {
+ type: 'START_DRAGGING_BLOCKS',
+ };
+}
+
+/**
+ * Returns an action object used in signalling that the user has stopped dragging blocks.
+ *
+ * @return {Object} Action object.
+ */
+export function stopDraggingBlocks() {
+ return {
+ type: 'STOP_DRAGGING_BLOCKS',
+ };
+}
+
/**
* Returns an action object used in signalling that the caret has entered formatted text.
*
diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js
index ac663d977e42b..c84ae07612e66 100644
--- a/packages/block-editor/src/store/reducer.js
+++ b/packages/block-editor/src/store/reducer.js
@@ -902,6 +902,26 @@ export function isTyping( state = false, action ) {
return state;
}
+/**
+ * Reducer returning dragging state.
+ *
+ * @param {boolean} state Current state.
+ * @param {Object} action Dispatched action.
+ *
+ * @return {boolean} Updated state.
+ */
+export function isDraggingBlocks( state = false, action ) {
+ switch ( action.type ) {
+ case 'START_DRAGGING_BLOCKS':
+ return true;
+
+ case 'STOP_DRAGGING_BLOCKS':
+ return false;
+ }
+
+ return state;
+}
+
/**
* Reducer returning whether the caret is within formatted text.
*
@@ -1329,6 +1349,7 @@ export function automaticChangeStatus( state, action ) {
export default combineReducers( {
blocks,
isTyping,
+ isDraggingBlocks,
isCaretWithinFormattedText,
selectionStart,
selectionEnd,
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index d2a009b59c639..49a6affeadc2b 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -927,6 +927,17 @@ export function isTyping( state ) {
return state.isTyping;
}
+/**
+ * Returns true if the user is dragging blocks, or false otherwise.
+ *
+ * @param {Object} state Global application state.
+ *
+ * @return {boolean} Whether user is dragging blocks.
+ */
+export function isDraggingBlocks( state ) {
+ return state.isDraggingBlocks;
+}
+
/**
* Returns true if the caret is within formatted text, or false otherwise.
*