Skip to content

Commit

Permalink
Try allowing blocks to be nested when dragging below, first attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
talldan committed Jul 16, 2020
1 parent 09be7e0 commit d93011b
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,18 @@ _Returns_

- `Array`: ids of top-level and descendant blocks.

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

Returns the dragged block client ids.

_Parameters_

- _state_ `Object`: Global application state.

_Returns_

- `boolean`: Whether user is dragging blocks.

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

Returns the client ID of the first block in the multi-selection set, or null
Expand Down Expand Up @@ -1341,6 +1353,10 @@ _Returns_

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

_Parameters_

- _clientIds_ `Array<string>`: An array of client ids being dragged

_Returns_

- `Object`: Action object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const BlockDraggable = ( {
elementId={ elementId || `block-${ clientIds[ 0 ] }` }
transferData={ transferData }
onDragStart={ ( event ) => {
startDraggingBlocks();
startDraggingBlocks( clientIds );
isDragging.current = true;

startScrolling( event );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,24 @@ import useOnHTMLDrop from '../use-block-drop-zone/use-on-html-drop';
import useOnFileDrop from '../use-block-drop-zone/use-on-file-drop';
import useOnBlockDrop from '../use-block-drop-zone/use-on-block-drop';

function getDropTargetBlocksData( ref, getRootClientId, getBlockIndex ) {
function getDropTargetBlocksData(
ref,
dragEventType,
getRootClientId,
getBlockIndex,
getDraggedBlockClientIds,
canInsertBlocks
) {
if ( ! ref.current ) {
return;
}

const isBlockDrag = dragEventType === 'default';

const draggedBlockClientIds = isBlockDrag
? getDraggedBlockClientIds()
: undefined;

const blockElements = Array.from(
ref.current.querySelectorAll( '[data-block]' )
);
Expand All @@ -32,6 +45,12 @@ function getDropTargetBlocksData( ref, getRootClientId, getBlockIndex ) {
blockIndex: getBlockIndex( clientId, rootClientId ),
element: blockElement,
orientation: 'vertical',
canInsertDraggedBlocksAsSibling: isBlockDrag
? canInsertBlocks( draggedBlockClientIds, rootClientId )
: true,
canInsertDraggedBlocksAsChild: isBlockDrag
? canInsertBlocks( draggedBlockClientIds, clientId )
: true,
};
} );
}
Expand All @@ -41,7 +60,7 @@ function getDropTargetBlocksData( ref, getRootClientId, getBlockIndex ) {
const ALLOWED_DROP_EDGES = [ 'top', 'bottom' ];

function getBlockNavigationDropTarget( blocksData, position ) {
let offset;
let candidateEdge;
let candidateBlockData;
let candidateDistance;

Expand All @@ -56,29 +75,51 @@ function getBlockNavigationDropTarget( blocksData, position ) {
if ( candidateDistance === undefined || distance < candidateDistance ) {
candidateDistance = distance;
candidateBlockData = blockData;
offset = edge === 'bottom' ? 1 : 0;
candidateEdge = edge;
}
} );

if ( ! candidateBlockData ) {
return;
}

const isDraggingBelow = candidateEdge === 'bottom';

// If the user is dragging towards the bottom of the block interpret that
// they're trying to next the dragged block.
if ( isDraggingBelow && candidateBlockData.canInsertDraggedBlocksAsChild ) {
return {
rootClientId: candidateBlockData.clientId,
blockIndex: 0,
};
}

const offset = isDraggingBelow ? 1 : 0;

return {
rootClientId: candidateBlockData.rootClientId,
blockIndex: candidateBlockData.blockIndex + offset,
};
}

export default function useBlockNavigationDropZone( ref ) {
const { getBlockRootClientId, getBlockIndex } = useSelect( ( select ) => {
const {
canInsertBlocks,
getBlockRootClientId,
getBlockIndex,
getDraggedBlockClientIds,
} = useSelect( ( select ) => {
const {
canInsertBlocks: _canInsertBlocks,
getBlockRootClientId: _getBlockRootClientId,
getBlockIndex: _getBlockIndex,
getDraggedBlockClientIds: _getDraggedBlockClientIds,
} = select( 'core/block-editor' );
return {
canInsertBlocks: _canInsertBlocks,
getBlockRootClientId: _getBlockRootClientId,
getBlockIndex: _getBlockIndex,
getDraggedBlockClientIds: _getDraggedBlockClientIds,
};
}, [] );

Expand All @@ -92,7 +133,7 @@ export default function useBlockNavigationDropZone( ref ) {
const onFilesDrop = useOnFileDrop( targetRootClientId, targetBlockIndex );
const onDrop = useOnBlockDrop( targetRootClientId, targetBlockIndex );

const { position } = useDropZone( {
const { position, type: dragEventType } = useDropZone( {
element: ref,
onFilesDrop,
onHTMLDrop,
Expand All @@ -108,8 +149,11 @@ export default function useBlockNavigationDropZone( ref ) {
if ( hasPosition ) {
blocksData.current = getDropTargetBlocksData(
ref,
dragEventType,
getBlockRootClientId,
getBlockIndex
getBlockIndex,
getDraggedBlockClientIds,
canInsertBlocks
);
}
}, [ hasPosition ] );
Expand Down
5 changes: 4 additions & 1 deletion packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,14 @@ export function stopTyping() {
/**
* Returns an action object used in signalling that the user has begun to drag blocks.
*
* @param {string[]} clientIds An array of client ids being dragged
*
* @return {Object} Action object.
*/
export function startDraggingBlocks() {
export function startDraggingBlocks( clientIds ) {
return {
type: 'START_DRAGGING_BLOCKS',
clientIds,
};
}

Expand Down
10 changes: 5 additions & 5 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1131,20 +1131,20 @@ export function isTyping( state = false, action ) {
}

/**
* Reducer returning dragging state.
* Reducer returning dragged block client id.
*
* @param {boolean} state Current state.
* @param {Object} action Dispatched action.
*
* @return {boolean} Updated state.
*/
export function isDraggingBlocks( state = false, action ) {
export function draggedBlocks( state = null, action ) {
switch ( action.type ) {
case 'START_DRAGGING_BLOCKS':
return true;
return action.clientIds;

case 'STOP_DRAGGING_BLOCKS':
return false;
return null;
}

return state;
Expand Down Expand Up @@ -1646,7 +1646,7 @@ export function highlightedBlock( state, action ) {
export default combineReducers( {
blocks,
isTyping,
isDraggingBlocks,
draggedBlocks,
isCaretWithinFormattedText,
selectionStart,
selectionEnd,
Expand Down
13 changes: 12 additions & 1 deletion packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,18 @@ export function isTyping( state ) {
* @return {boolean} Whether user is dragging blocks.
*/
export function isDraggingBlocks( state ) {
return state.isDraggingBlocks;
return !! state.draggedBlocks;
}

/**
* Returns the dragged block client ids.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether user is dragging blocks.
*/
export function getDraggedBlockClientIds( state ) {
return state.draggedBlocks;
}

/**
Expand Down

0 comments on commit d93011b

Please sign in to comment.