Skip to content

Commit

Permalink
Refactor the draggable component to avoid passing around unnecessary …
Browse files Browse the repository at this point in the history
…props
  • Loading branch information
youknowriad committed Nov 26, 2019
1 parent e4b5330 commit 760a925
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down
71 changes: 57 additions & 14 deletions packages/block-editor/src/components/block-draggable/index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,73 @@
/**
* External dependencies
*/
import { castArray } from 'lodash';

/**
* WordPress dependencies
*/
import { Draggable } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect, useRef } from '@wordpress/element';

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

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

const BlockDraggable = ( { children, clientId, rootClientId, blockElementId, index, onDragStart, onDragEnd } ) => {
// Stop dragging blocks if the block draggable is unmounted
useEffect( () => {
return () => {
if ( isDragging.current ) {
stopDraggingBlocks();
}
};
}, [] );

if ( ! isDraggable ) {
return null;
}

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

return (
<Draggable
elementId={ blockElementId }
transferData={ transferData }
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
onDragStart={ () => {
startDraggingBlocks();
isDragging.current = true;
} }
onDragEnd={ () => {
stopDraggingBlocks();
isDragging.current = false;
} }
>
{
( { onDraggableStart, onDraggableEnd } ) => {
Expand All @@ -31,11 +81,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;
28 changes: 10 additions & 18 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { __, sprintf } from '@wordpress/i18n';
import {
withDispatch,
withSelect,
useSelect,
} from '@wordpress/data';
import { withViewportMatch } from '@wordpress/viewport';
import { compose, pure, ifCondition } from '@wordpress/compose';
Expand Down Expand Up @@ -77,9 +78,7 @@ function BlockListBlock( {
isTypingWithinBlock,
isCaretWithinFormattedText,
isEmptyDefaultBlock,
isMovable,
isParentOfSelectedBlock,
isDraggable,
isSelectionEnabled,
className,
name,
Expand All @@ -103,6 +102,14 @@ function BlockListBlock( {
isNavigationMode,
enableNavigationMode,
} ) {
// In addition to withSelect, we should favor using useSelect in this component going forward
// to avoid leaking new props to the public API (editor.BlockListBlock filter)
const { isDraggingBlocks } = useSelect( ( select ) => {
return {
isDraggingBlocks: select( 'core/block-editor' ).isDraggingBlocks(),
};
} );

// Random state used to rerender the component if needed, ideally we don't need this
const [ , updateRerenderState ] = useState( {} );
const rerender = () => updateRerenderState( {} );
Expand Down Expand Up @@ -171,15 +178,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 );
Expand Down Expand Up @@ -422,6 +420,7 @@ function BlockListBlock( {
const shouldShowInsertionPoint =
( isPartOfMultiSelection && isFirstMultiSelected ) ||
! isPartOfMultiSelection;
const isDragging = isDraggingBlocks && ( isSelected || isPartOfMultiSelection );

// The wp-block className is important for editor styles.
// Generate the wrapper class names handling the different states of the block.
Expand Down Expand Up @@ -454,14 +453,7 @@ function BlockListBlock( {
const blockMover = (
<BlockMover
clientIds={ clientId }
blockElementId={ blockElementId }
isHidden={ ! isSelected }
isDraggable={
isDraggable !== false &&
( ! isPartOfMultiSelection && isMovable )
}
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
__experimentalOrientation={ moverDirection }
/>
);
Expand Down
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
Expand Up @@ -196,7 +196,6 @@ class BlockList extends Component {
blockClientIds,
rootClientId,
__experimentalMoverDirection: moverDirection = 'vertical',
isDraggable,
selectedBlockClientId,
multiSelectedBlockClientIds,
hasMultiSelection,
Expand Down Expand Up @@ -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
Expand Down
39 changes: 0 additions & 39 deletions packages/block-editor/src/components/block-mover/drag-handle.js

This file was deleted.

27 changes: 16 additions & 11 deletions packages/block-editor/src/components/block-mover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { withInstanceId, compose } from '@wordpress/compose';
*/
import { getBlockMoverDescription } from './mover-description';
import { leftArrow, rightArrow, upArrow, downArrow, dragHandle } from './icons';
import { IconDragHandle } from './drag-handle';
import BlockDraggable from '../block-draggable';

export class BlockMover extends Component {
constructor() {
Expand All @@ -44,7 +44,7 @@ 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;
if ( isLocked || ( isFirst && isLast && ! rootClientId ) ) {
Expand Down Expand Up @@ -98,15 +98,20 @@ export class BlockMover extends Component {
onFocus={ this.onFocus }
onBlur={ this.onBlur }
/>
<IconDragHandle
className="editor-block-mover__control block-editor-block-mover__control"
icon={ dragHandle }
clientId={ clientIds }
blockElementId={ blockElementId }
isVisible={ isDraggable }
onDragStart={ onDragStart }
onDragEnd={ onDragEnd }
/>

<BlockDraggable clientIds={ clientIds }>
{ ( { onDraggableStart, onDraggableEnd } ) => (
<IconButton
icon={ dragHandle }
className="block-editor-block-mover__control-drag-handle editor-block-mover__control block-editor-block-mover__control"
aria-hidden="true"
onDragStart={ onDraggableStart }
onDragEnd={ onDraggableEnd }
draggable
/>
) }
</BlockDraggable>

<IconButton
className="editor-block-mover__control block-editor-block-mover__control"
onClick={ isLast ? null : onMoveDown }
Expand Down
Loading

0 comments on commit 760a925

Please sign in to comment.