Skip to content

Commit

Permalink
Prototype move blocks between levels with keyboard
Browse files Browse the repository at this point in the history
  • Loading branch information
tellthemachines committed May 26, 2020
1 parent e883aab commit d9e3c24
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,18 @@ _Returns_

- `?boolean`: Whether the insertion point is visible or not.

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

Returns whether block moving mode is enabled.

_Parameters_

- _state_ `Object`: Editor state.

_Returns_

- `string`: Client Id of moving block.

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

Returns true if the client ID occurs within the block multi-selection, or
Expand Down Expand Up @@ -1255,6 +1267,14 @@ _Parameters_

- _clientId_ `string`: Block client ID.

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

Generators that triggers an action used to enable or disable the block moving mode.

_Parameters_

- _isBlockMovingMode_ `string`: Enable/Disable block moving mode.

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

Returns an action object that sets whether the block has controlled innerblocks.
Expand Down
9 changes: 8 additions & 1 deletion packages/block-editor/src/components/block-actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function BlockActions( {
onGroup,
onInsertAfter,
onInsertBefore,
onMoveTo,
onRemove,
onUngroup,
blocks,
Expand All @@ -31,6 +32,7 @@ function BlockActions( {
onGroup,
onInsertAfter,
onInsertBefore,
onMoveTo,
onRemove,
onUngroup,
blocks,
Expand Down Expand Up @@ -73,13 +75,14 @@ export default compose( [
} ),
withDispatch( ( dispatch, props, { select } ) => {
const { clientIds, blocks } = props;

const {
removeBlocks,
replaceBlocks,
duplicateBlocks,
insertAfterBlock,
insertBeforeBlock,
setBlockMovingMode,
setNavigationMode,
} = dispatch( 'core/block-editor' );

return {
Expand All @@ -95,6 +98,10 @@ export default compose( [
onInsertAfter() {
insertAfterBlock( last( castArray( clientIds ) ) );
},
onMoveTo() {
setNavigationMode( true );
setBlockMovingMode( clientIds[ 0 ] );
},
onGroup() {
if ( ! blocks.length ) {
return;
Expand Down
16 changes: 13 additions & 3 deletions packages/block-editor/src/components/block-list/breadcrumb.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand Down Expand Up @@ -36,16 +41,17 @@ function BlockBreadcrumb( {
const {
__unstableGetBlockWithoutInnerBlocks,
getBlockIndex,
isBlockMovingMode,
} = select( 'core/block-editor' );
const index = getBlockIndex( clientId, rootClientId );
const { name, attributes } = __unstableGetBlockWithoutInnerBlocks(
clientId
);
return { index, name, attributes };
return { index, name, attributes, isBlockMovingMode };
},
[ clientId, rootClientId ]
);
const { index, name, attributes } = selected;
const { index, name, attributes, isBlockMovingMode } = selected;
const { setNavigationMode, removeBlock } = useDispatch(
'core/block-editor'
);
Expand Down Expand Up @@ -73,8 +79,12 @@ function BlockBreadcrumb( {
moverDirection
);

const classNames = classnames( 'block-editor-block-list__breadcrumb', {
'is-navigate-mode': !! isBlockMovingMode(),
} );

return (
<div className="block-editor-block-list__breadcrumb" { ...props }>
<div className={ classNames } { ...props }>
<Button
ref={ ref }
onClick={ () => setNavigationMode( false ) }
Expand Down
26 changes: 26 additions & 0 deletions packages/block-editor/src/components/block-list/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,34 @@
}
}
}


.is-navigate-mode.is-block-moving-mode & .block-editor-block-list__block.is-selected {
&::before {
content: "";
position: absolute;
z-index: 0;
pointer-events: none;
transition:
border-color 0.1s linear,
border-style 0.1s linear,
box-shadow 0.1s linear;
right: 0;
left: 0;
top: -$default-block-margin / 2;
border-radius: $radius-block-ui;
border-top: 4px solid $blue-medium-focus;
}
&::after {
content: none;
}
}
}

.is-navigate-mode.block-editor-block-list__breadcrumb {
// Should be invisible but not unfocusable.
opacity: 0;
}

/**
* Block styles and alignments
Expand Down
72 changes: 67 additions & 5 deletions packages/block-editor/src/components/writing-flow/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
TAB,
isKeyboardEvent,
ESCAPE,
SPACE,
} from '@wordpress/keycodes';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
Expand Down Expand Up @@ -203,6 +204,10 @@ function selector( select ) {
hasMultiSelection,
getBlockOrder,
isNavigationMode,
isBlockMovingMode,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
isSelectionEnabled,
getBlockSelectionStart,
isMultiSelecting,
Expand All @@ -226,6 +231,10 @@ function selector( select ) {
hasMultiSelection: hasMultiSelection(),
blocks: getBlockOrder(),
isNavigationMode: isNavigationMode(),
isBlockMovingMode,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
isSelectionEnabled: isSelectionEnabled(),
blockSelectionStart: getBlockSelectionStart(),
isMultiSelecting: isMultiSelecting(),
Expand Down Expand Up @@ -263,17 +272,22 @@ export default function WritingFlow( { children } ) {
hasMultiSelection,
blocks,
isNavigationMode,
isBlockMovingMode,
isSelectionEnabled,
blockSelectionStart,
isMultiSelecting,
getBlockIndex,
getBlockRootClientId,
getClientIdsOfDescendants,
} = useSelect( selector, [] );
const {
multiSelect,
selectBlock,
clearSelectedBlock,
setNavigationMode,
setBlockMovingMode,
moveBlockToPosition,
} = useDispatch( 'core/block-editor' );

function onMouseDown( event ) {
verticalRect.current = null;

Expand Down Expand Up @@ -367,6 +381,7 @@ export default function WritingFlow( { children } ) {
const isRight = keyCode === RIGHT;
const isTab = keyCode === TAB;
const isEscape = keyCode === ESCAPE;
const isSpace = keyCode === SPACE;
const isReverse = isUp || isLeft;
const isHorizontal = isLeft || isRight;
const isVertical = isUp || isDown;
Expand All @@ -380,11 +395,57 @@ export default function WritingFlow( { children } ) {
if ( isNavigationMode ) {
const navigateUp = ( isTab && isShift ) || isUp;
const navigateDown = ( isTab && ! isShift ) || isDown;
const focusedBlockUid = navigateUp
? selectionBeforeEndClientId
: selectionAfterEndClientId;
// Move out of current nesting level (no effect if at root level).
const navigateOut = isLeft;
// Move into next nesting level (no effect if the current block has no innerBlocks).
const navigateIn = isRight;

let focusedBlockUid;
if ( navigateUp ) {
focusedBlockUid = selectionBeforeEndClientId;
} else if ( navigateDown ) {
focusedBlockUid = selectionAfterEndClientId;
} else if ( navigateOut ) {
focusedBlockUid =
getBlockRootClientId( selectedBlockClientId ) ||
selectedBlockClientId;
} else if ( navigateIn ) {
focusedBlockUid =
getClientIdsOfDescendants( [
selectedBlockClientId,
] )[ 0 ] || selectedBlockClientId;
}
const startingBlockClientId = isBlockMovingMode();

if ( navigateDown || navigateUp ) {
if ( isSpace && startingBlockClientId ) {
const sourceRoot = getBlockRootClientId(
startingBlockClientId
);
const destRoot = getBlockRootClientId( selectedBlockClientId );
const sourceBlockIndex = getBlockIndex(
startingBlockClientId,
sourceRoot
);
let destinationBlockIndex = getBlockIndex(
selectedBlockClientId,
destRoot
);
if (
sourceBlockIndex < destinationBlockIndex &&
sourceRoot === destRoot
) {
destinationBlockIndex -= 1;
}
moveBlockToPosition(
startingBlockClientId,
sourceRoot,
destRoot,
destinationBlockIndex
);
selectBlock( startingBlockClientId );
setBlockMovingMode( '' );
}
if ( navigateDown || navigateUp || navigateOut || navigateIn ) {
if ( focusedBlockUid ) {
event.preventDefault();
selectBlock( focusedBlockUid );
Expand Down Expand Up @@ -585,6 +646,7 @@ export default function WritingFlow( { children } ) {

const className = classnames( 'block-editor-writing-flow', {
'is-navigate-mode': isNavigationMode,
'is-block-moving-mode': !! isBlockMovingMode(),
} );

// Disable reason: Wrapper itself is non-interactive, but must capture
Expand Down
12 changes: 12 additions & 0 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,18 @@ export function* setNavigationMode( isNavigationMode = true ) {
}
}

/**
* Generators that triggers an action used to enable or disable the block moving mode.
*
* @param {string} isBlockMovingMode Enable/Disable block moving mode.
*/
export function* setBlockMovingMode( isBlockMovingMode = '' ) {
yield {
type: 'SET_BLOCK_MOVING_MODE',
isBlockMovingMode,
};
}

/**
* Generator that triggers an action used to duplicate a list of blocks.
*
Expand Down
19 changes: 19 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,24 @@ export function isNavigationMode( state = false, action ) {
return state;
}

/**
* Reducer returning whether the block moving mode is enabled or not.
*
* @param {string} state Current state.
* @param {Object} action Dispatched action.
*
* @return {string} Updated state.
*/
export function isBlockMovingMode( state = '', action ) {
// Let inserting block always trigger Edit mode.

if ( action.type === 'SET_BLOCK_MOVING_MODE' ) {
return action.isBlockMovingMode;
}

return state;
}

/**
* Reducer return an updated state representing the most recent block attribute
* update. The state is structured as an object where the keys represent the
Expand Down Expand Up @@ -1621,6 +1639,7 @@ export default combineReducers( {
preferences,
lastBlockAttributesChange,
isNavigationMode,
isBlockMovingMode,
automaticChangeStatus,
highlightedBlock,
} );
11 changes: 11 additions & 0 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,17 @@ export function isNavigationMode( state ) {
return state.isNavigationMode;
}

/**
* Returns whether block moving mode is enabled.
*
* @param {Object} state Editor state.
*
* @return {string} Client Id of moving block.
*/
export function isBlockMovingMode( state ) {
return state.isBlockMovingMode;
}

/**
* Returns true if the last change was an automatic change, false otherwise.
*
Expand Down

0 comments on commit d9e3c24

Please sign in to comment.