Skip to content

Commit

Permalink
Move the block movers to the block toolbar
Browse files Browse the repository at this point in the history
youknowriad committed Nov 26, 2019
1 parent cc378e8 commit e2a8e8e
Showing 17 changed files with 169 additions and 391 deletions.
Original file line number Diff line number Diff line change
@@ -756,6 +756,18 @@ _Returns_

- `boolean`: Whether the caret is within formatted text.

<a name="isDraggingBlocks" href="#isDraggingBlocks">#</a> **isDraggingBlocks**

Returns true if the user is dragging blocks, or false otherwise.

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether user is dragging blocks.

<a name="isFirstMultiSelectedBlock" href="#isFirstMultiSelectedBlock">#</a> **isFirstMultiSelectedBlock**

Returns true if a multi-selection exists, and the block corresponding to the
@@ -1177,6 +1189,14 @@ _Returns_

- `Object`: Action object.

<a name="startDraggingBlocks" href="#startDraggingBlocks">#</a> **startDraggingBlocks**

Returns an action object used in signalling that the user has begun to drag blocks.

_Returns_

- `Object`: Action object.

<a name="startMultiSelect" href="#startMultiSelect">#</a> **startMultiSelect**

Returns an action object used in signalling that a block multi-selection has started.
@@ -1193,6 +1213,14 @@ _Returns_

- `Object`: Action object.

<a name="stopDraggingBlocks" href="#stopDraggingBlocks">#</a> **stopDraggingBlocks**

Returns an action object used in signalling that the user has stopped dragging blocks.

_Returns_

- `Object`: Action object.

<a name="stopMultiSelect" href="#stopMultiSelect">#</a> **stopMultiSelect**

Returns an action object used in signalling that block multi-selection stopped.
4 changes: 0 additions & 4 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
@@ -332,10 +332,6 @@ _Related_

- <https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/media-upload/README.md>

<a name="MultiBlocksSwitcher" href="#MultiBlocksSwitcher">#</a> **MultiBlocksSwitcher**

Undocumented declaration.

<a name="MultiSelectScrollIntoView" href="#MultiSelectScrollIntoView">#</a> **MultiSelectScrollIntoView**

Undocumented declaration.
43 changes: 29 additions & 14 deletions packages/block-editor/src/components/block-draggable/index.js
Original file line number Diff line number Diff line change
@@ -2,22 +2,44 @@
* WordPress dependencies
*/
import { Draggable } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';

const BlockDraggable = ( { children, clientId, rootClientId, blockElementId, index, onDragStart, onDragEnd } ) => {
const BlockDraggable = ( { children, clientIds } ) => {
const { srcRootClientId, index, isDraggable } = useSelect( ( select ) => {
const {
getBlockIndex,
getBlockRootClientId,
getTemplateLock,
} = select( 'core/block-editor' );
const rootClientId = clientIds.length === 1 ? getBlockRootClientId( clientIds[ 0 ] ) : null;
const templateLock = rootClientId ? getTemplateLock( rootClientId ) : null;

return {
index: getBlockIndex( clientIds[ 0 ], rootClientId ),
srcRootClientId: rootClientId,
isDraggable: clientIds.length === 1 && 'all' !== templateLock,
};
}, [ clientIds ] );
const { startDraggingBlocks, stopDraggingBlocks } = useDispatch( 'core/block-editor' );

if ( ! isDraggable ) {
return null;
}

const blockElementId = `block-${ clientIds[ 0 ] }`;
const transferData = {
type: 'block',
srcIndex: index,
srcRootClientId: rootClientId,
srcClientId: clientId,
srcClientId: clientIds[ 0 ],
srcRootClientId,
};

return (
<Draggable
elementId={ blockElementId }
transferData={ transferData }
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
onDragStart={ startDraggingBlocks }
onDragEnd={ stopDraggingBlocks }
>
{
( { 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;

This file was deleted.

55 changes: 5 additions & 50 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
@@ -35,16 +35,13 @@ 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';
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 = (
<BlockMover
clientIds={ clientId }
blockElementId={ blockElementId }
isHidden={ ! isSelected }
isDraggable={
isDraggable !== false &&
( ! isPartOfMultiSelection && isMovable )
}
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
__experimentalOrientation={ moverDirection }
/>
);

// 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 && (
<BlockMultiControls
rootClientId={ rootClientId }
moverDirection={ moverDirection }
/>
) }
<div
className={ classnames(
'editor-block-list__block-edit block-editor-block-list__block-edit',
{ 'has-mover-inside': moverDirection === 'horizontal' },
) }
>
{ shouldRenderMovers && ( moverDirection === 'vertical' ) && blockMover }
{ shouldShowBreadcrumb && (
<BlockBreadcrumb
clientId={ clientId }
@@ -577,7 +535,6 @@ function BlockListBlock( {
{ isValid && mode === 'html' && (
<BlockHtml clientId={ clientId } />
) }
{ shouldRenderMovers && ( moverDirection === 'horizontal' ) && blockMover }
{ ! isValid && [
<BlockInvalidWarning
key="invalid-warning"
@@ -589,9 +546,6 @@ function BlockListBlock( {
] }
</BlockCrashBoundary>
{ !! hasError && <BlockCrashWarning /> }
{ shouldShowMobileToolbar && (
<BlockMobileToolbar clientId={ clientId } moverDirection={ moverDirection } />
) }
</IgnoreNestedEvents>
</div>
{ showInserterShortcuts && (
@@ -625,6 +579,7 @@ const applyWithSelect = withSelect(
isBlockMultiSelected,
isFirstMultiSelectedBlock,
isTyping,
isDraggingBlocks,
isCaretWithinFormattedText,
getBlockMode,
isSelectionEnabled,
@@ -644,15 +599,15 @@ 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.
// It happens now because the order in withSelect rendering is not correct.
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
2 changes: 0 additions & 2 deletions packages/block-editor/src/components/block-list/index.js
Original file line number Diff line number Diff line change
@@ -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
39 changes: 0 additions & 39 deletions packages/block-editor/src/components/block-list/multi-controls.js

This file was deleted.

80 changes: 3 additions & 77 deletions packages/block-editor/src/components/block-list/style.scss
Original file line number Diff line number Diff line change
@@ -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,19 +798,21 @@

// 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;
}

@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;
26 changes: 11 additions & 15 deletions packages/block-editor/src/components/block-mover/drag-handle.js
Original file line number Diff line number Diff line change
@@ -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 (
<BlockDraggable
clientId={ clientId }
blockElementId={ blockElementId }
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
>
<BlockDraggable clientIds={ clientIds }>
{
( { onDraggableStart, onDraggableEnd } ) => (
<div
<IconButton
icon={ dragHandle }
className={ dragHandleClassNames }
aria-hidden="true"
onDragStart={ onDraggableStart }
onDragEnd={ onDraggableEnd }
draggable
>
{ icon }
</div>
/>
) }
</BlockDraggable>
);
28 changes: 11 additions & 17 deletions packages/block-editor/src/components/block-mover/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<div className={ classnames( 'editor-block-mover block-editor-block-mover', { 'is-visible': isFocused || ! isHidden, 'is-horizontal': orientation === 'horizontal' } ) }>
<Toolbar className={ classnames( 'editor-block-mover block-editor-block-mover', { 'is-visible': isFocused || ! isHidden, 'is-horizontal': orientation === 'horizontal' } ) }>
<IconButton
className="editor-block-mover__control block-editor-block-mover__control"
onClick={ isFirst ? null : onMoveUp }
@@ -99,13 +99,8 @@ export class BlockMover extends Component {
onBlur={ this.onBlur }
/>
<IconDragHandle
clientIds={ clientIds }
className="editor-block-mover__control block-editor-block-mover__control"
icon={ dragHandle }
clientId={ clientIds }
blockElementId={ blockElementId }
isVisible={ isDraggable }
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
/>
<IconButton
className="editor-block-mover__control block-editor-block-mover__control"
@@ -146,21 +141,20 @@ export class BlockMover extends Component {
)
}
</span>
</div>
</Toolbar>
);
}
}

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,
93 changes: 0 additions & 93 deletions packages/block-editor/src/components/block-mover/style.scss
Original file line number Diff line number Diff line change
@@ -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;

This file was deleted.

58 changes: 28 additions & 30 deletions packages/block-editor/src/components/block-toolbar/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<div className="editor-block-toolbar block-editor-block-toolbar">
<MultiBlocksSwitcher />
<BlockSettingsMenu clientIds={ blockClientIds } />
</div>
);
if ( blockIds.length === 0 ) {
return null;
}
const shouldShowVisualToolbar = isValid && mode === 'visual';
const isMultiToolbar = blockIds.length > 1;

return (
<div className="editor-block-toolbar block-editor-block-toolbar">
{ mode === 'visual' && isValid && (
<BlockMover
clientIds={ blockIds }
__experimentalOrientation={ moverDirection }
/>
{ ( shouldShowVisualToolbar || isMultiToolbar ) && <BlockSwitcher clientIds={ blockIds } /> }
{ shouldShowVisualToolbar && ! isMultiToolbar && (
<>
<BlockSwitcher clientIds={ blockClientIds } />
<BlockControls.Slot bubblesVirtually className="block-editor-block-toolbar__slot" />
<BlockFormatControls.Slot bubblesVirtually className="block-editor-block-toolbar__slot" />
</>
) }
<BlockSettingsMenu clientIds={ blockClientIds } />
<BlockSettingsMenu clientIds={ blockIds } />
</div>
);
}

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;
1 change: 0 additions & 1 deletion packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
@@ -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';
22 changes: 22 additions & 0 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
@@ -655,6 +655,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.
*
21 changes: 21 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
@@ -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,
11 changes: 11 additions & 0 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
@@ -928,6 +928,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.
*

0 comments on commit e2a8e8e

Please sign in to comment.