Skip to content

Commit

Permalink
Block Editor: Add block zooming.
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras committed Jul 13, 2019
1 parent cf1da64 commit fab407a
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 5 deletions.
1 change: 1 addition & 0 deletions assets/stylesheets/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ $z-layers: (
".block-editor-block-list__block {core/image aligned wide or fullwide}": 20,
".block-library-classic__toolbar": 10,
".block-editor-block-list__layout .reusable-block-indicator": 1,
".block-editor-block-list__zoom_out": 7, // On top of insertion point.
".block-editor-block-list__breadcrumb": 2,
".components-form-toggle__input": 1,
".components-panel__header.edit-post-sidebar__panel-tabs": -1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,18 @@ _Returns_

- `?string`: Block Template Lock

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

Returns the zoomed block client IDs, if any.

_Parameters_

- _state_ `Object`: Editor state.

_Returns_

- `?(Array<string>)`: Client IDs of zoomed blocks.

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

Determines whether there are items to show in the inserter.
Expand Down Expand Up @@ -812,6 +824,14 @@ _Returns_

- `Object`: Action object.

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

Returns an action object that zooms out from any zoomed in blocks.

_Returns_

- `Object`: Action object.

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

Returns an action object used in signalling that the caret has entered formatted text.
Expand Down Expand Up @@ -1207,4 +1227,16 @@ _Returns_

Undocumented declaration.

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

Returns an action object that zooms the editor into a list of specified blocks.

_Parameters_

- _clientIds_ `Array<string>`: Client IDs of the blocks to zoom into.

_Returns_

- `Object`: Action object.

<!-- END TOKEN(Autogenerated actions) -->
16 changes: 15 additions & 1 deletion packages/block-editor/src/components/block-actions/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { castArray, first, last, every } from 'lodash';
import { castArray, first, last, every, flatMap } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -11,6 +11,7 @@ import { withSelect, withDispatch } from '@wordpress/data';
import { cloneBlock, hasBlockSupport, switchToBlockType } from '@wordpress/blocks';

function BlockActions( {
onZoom,
onDuplicate,
onRemove,
onInsertBefore,
Expand All @@ -22,6 +23,7 @@ function BlockActions( {
children,
} ) {
return children( {
onZoom,
onDuplicate,
onRemove,
onInsertAfter,
Expand Down Expand Up @@ -65,6 +67,7 @@ export default compose( [
} = props;

const {
zoomBlocks,
insertBlocks,
multiSelect,
removeBlocks,
Expand All @@ -73,6 +76,17 @@ export default compose( [
} = dispatch( 'core/block-editor' );

return {
onZoom() {
const { getSelectedBlockClientIds, getBlockOrder } = select(
'core/block-editor'
);
zoomBlocks(
flatMap( getSelectedBlockClientIds(), ( clientId ) => {
const descendants = getBlockOrder( clientId );
return descendants.length ? descendants : clientId;
} )
);
},
onDuplicate() {
if ( isLocked || ! canDuplicate ) {
return;
Expand Down
29 changes: 28 additions & 1 deletion packages/block-editor/src/components/block-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import {
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import {
withSelect,
withDispatch,
__experimentalAsyncModeProvider as AsyncModeProvider,
} from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { IconButton } from '@wordpress/components';

/**
* Internal dependencies
Expand Down Expand Up @@ -204,11 +206,24 @@ class BlockList extends Component {
multiSelectedBlockClientIds,
hasMultiSelection,
renderAppender,
hasZoomedBlocks,
enableAnimation,
onZoomOut,
} = this.props;

return (
<div className="editor-block-list__layout block-editor-block-list__layout">
{ hasZoomedBlocks && (
<IconButton
className="block-editor-block-list__zoom-out"
onClick={ onZoomOut }
icon="search"
label={ __( 'Zoom Out' ) }
>
{ __( 'Zoom Out' ) }
</IconButton>
) }

{ blockClientIds.map( ( clientId ) => {
const isBlockInSelection = hasMultiSelection ?
multiSelectedBlockClientIds.includes( clientId ) :
Expand Down Expand Up @@ -254,6 +269,7 @@ export default compose( [
withSelect( ( select, ownProps ) => {
const {
getBlockOrder,
getZoomedBlockClientIds,
isSelectionEnabled,
isMultiSelecting,
getMultiSelectedBlocksStartClientId,
Expand All @@ -265,16 +281,25 @@ export default compose( [
} = select( 'core/block-editor' );

const { rootClientId } = ownProps;
let blockClientIds = rootClientId ?
getBlockOrder( rootClientId ) :
getZoomedBlockClientIds();
let hasZoomedBlocks = ! rootClientId;
if ( ! blockClientIds ) {
blockClientIds = getBlockOrder();
hasZoomedBlocks = false;
}

return {
blockClientIds: getBlockOrder( rootClientId ),
blockClientIds,
selectionStart: getMultiSelectedBlocksStartClientId(),
selectionEnd: getMultiSelectedBlocksEndClientId(),
isSelectionEnabled: isSelectionEnabled(),
isMultiSelecting: isMultiSelecting(),
selectedBlockClientId: getSelectedBlockClientId(),
multiSelectedBlockClientIds: getMultiSelectedBlockClientIds(),
hasMultiSelection: hasMultiSelection(),
hasZoomedBlocks,
enableAnimation: getGlobalBlockCount() <= BLOCK_ANIMATION_THRESHOLD,
};
} ),
Expand All @@ -283,12 +308,14 @@ export default compose( [
startMultiSelect,
stopMultiSelect,
multiSelect,
clearZoomedBlocks,
} = dispatch( 'core/block-editor' );

return {
onStartMultiSelect: startMultiSelect,
onStopMultiSelect: stopMultiSelect,
onMultiSelect: multiSelect,
onZoomOut: clearZoomedBlocks,
};
} ),
] )( BlockList );
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ function useMovingAnimation( ref, isSelected, enableAnimation, triggerAnimationO
ref.current.style.transform = 'none';
const destination = ref.current.getBoundingClientRect();
const newTransform = {
x: previous ? previous.left - destination.left : 0,
y: previous ? previous.top - destination.top : 0,
x: previous ? previous.left - destination.left : -50,
y: previous ? previous.top - destination.top : -50,
};
ref.current.style.transform = newTransform.x === 0 && newTransform.y === 0 ?
undefined :
Expand Down
10 changes: 10 additions & 0 deletions packages/block-editor/src/components/block-list/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
}
}

.block-editor-block-list__zoom-out {
background: $white;
border-radius: 0;
float: right;
margin-top: -50px;
position: sticky;
top: 0;
z-index: z-index(".block-editor-block-list__zoom_out");
}

.block-editor-block-list__layout .block-editor-block-list__block.is-selected { // Needs specificity to override inherited styles.
// While block is being dragged, dim the slot dragged from, and hide some UI.
&.is-dragging {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function BlockSettingsMenu( { clientIds } ) {

return (
<BlockActions clientIds={ clientIds }>
{ ( { onDuplicate, onRemove, onInsertAfter, onInsertBefore, canDuplicate, isLocked } ) => (
{ ( { onZoom, onDuplicate, onRemove, onInsertAfter, onInsertBefore, canDuplicate, isLocked } ) => (
<Toolbar>
<DropdownMenu
icon="ellipsis"
Expand All @@ -46,6 +46,13 @@ export function BlockSettingsMenu( { clientIds } ) {
{ ( { onClose } ) => (
<>
<MenuGroup>
<MenuItem
className="editor-block-settings-menu__control block-editor-block-settings-menu__control"
onClick={ flow( onClose, onZoom ) }
icon="search"
>
{ __( 'Zoom' ) }
</MenuItem>
<__experimentalBlockSettingsMenuFirstItem.Slot
fillProps={ { onClose } }
/>
Expand Down
25 changes: 25 additions & 0 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,31 @@ export function replaceInnerBlocks( rootClientId, blocks, updateSelection = true
};
}

/**
* Returns an action object that zooms the editor into a list of specified blocks.
*
* @param {string[]} clientIds Client IDs of the blocks to zoom into.
*
* @return {Object} Action object.
*/
export function zoomBlocks( clientIds ) {
return {
type: 'ZOOM_BLOCKS',
clientIds,
};
}

/**
* Returns an action object that zooms out from any zoomed in blocks.
*
* @return {Object} Action object.
*/
export function clearZoomedBlocks() {
return {
type: 'CLEAR_ZOOMED_BLOCKS',
};
}

/**
* Returns an action object used to toggle the block editing mode between
* visual and HTML modes.
Expand Down
20 changes: 20 additions & 0 deletions packages/block-editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,25 @@ export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action )
return state;
}

/**
* Reducer returning the block zoom's state.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
*
* @return {Object} Updated state.
*/
export function blockZoom( state, action ) {
switch ( action.type ) {
case 'ZOOM_BLOCKS':
return action.clientIds;
case 'CLEAR_ZOOMED_BLOCKS':
return null;
}

return state;
}

export function blocksMode( state = {}, action ) {
if ( action.type === 'TOGGLE_BLOCK_MODE' ) {
const { clientId } = action;
Expand Down Expand Up @@ -1228,6 +1247,7 @@ export default combineReducers( {
isTyping,
isCaretWithinFormattedText,
blockSelection,
blockZoom,
blocksMode,
blockListSettings,
insertionPoint,
Expand Down
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 @@ -889,6 +889,17 @@ export function isSelectionEnabled( state ) {
return state.blockSelection.isEnabled;
}

/**
* Returns the zoomed block client IDs, if any.
*
* @param {Object} state Editor state.
*
* @return {?(string[])} Client IDs of zoomed blocks.
*/
export function getZoomedBlockClientIds( state ) {
return state.blockZoom;
}

/**
* Returns the block's editing mode, defaulting to "visual" if not explicitly
* assigned.
Expand Down

0 comments on commit fab407a

Please sign in to comment.