From d6cc40504973a2e60848dbed47915217a00911d0 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 12 Mar 2019 11:05:04 +0100 Subject: [PATCH 1/5] This PR moves the reusable blocks buttons to the editor module --- .../developers/data/data-core-block-editor.md | 12 ++++++ .../block-editor-keyboard-shortcuts/index.js | 6 +-- .../components/block-settings-menu/index.js | 12 ------ .../src/components/block-toolbar/index.js | 12 ++---- .../src/components/copy-handler/index.js | 11 ++--- packages/block-editor/src/store/selectors.js | 27 ++++++++++--- .../editor/src/components/provider/index.js | 2 + .../reusable-blocks-buttons/index.js | 40 +++++++++++++++++++ .../reusable-block-convert-button.js | 0 .../reusable-block-delete-button.js | 0 10 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 packages/editor/src/components/reusable-blocks-buttons/index.js rename packages/{block-editor/src/components/block-settings-menu => editor/src/components/reusable-blocks-buttons}/reusable-block-convert-button.js (100%) rename packages/{block-editor/src/components/block-settings-menu => editor/src/components/reusable-blocks-buttons}/reusable-block-delete-button.js (100%) diff --git a/docs/designers-developers/developers/data/data-core-block-editor.md b/docs/designers-developers/developers/data/data-core-block-editor.md index fb3f337dd59cd2..38110f42aa2c75 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -327,6 +327,18 @@ This position is to used to position the caret properly when the selected block Selected block. +### getSelectedBlockClientIds + +Returns the current selection set of block client IDs (multiselection or single selection). + +*Parameters* + + * state: Editor state. + +*Returns* + +Multi-selected block client IDs. + ### getMultiSelectedBlockClientIds Returns the current multi-selection set of block client IDs, or an empty diff --git a/packages/block-editor/src/components/block-editor-keyboard-shortcuts/index.js b/packages/block-editor/src/components/block-editor-keyboard-shortcuts/index.js index 4e97184cd93f97..9b30976a27ee02 100644 --- a/packages/block-editor/src/components/block-editor-keyboard-shortcuts/index.js +++ b/packages/block-editor/src/components/block-editor-keyboard-shortcuts/index.js @@ -123,14 +123,12 @@ export default compose( [ withSelect( ( select ) => { const { getBlockOrder, - getMultiSelectedBlockClientIds, + getSelectedBlockClientIds, hasMultiSelection, getBlockRootClientId, getTemplateLock, - getSelectedBlockClientId, } = select( 'core/block-editor' ); - const selectedBlockClientId = getSelectedBlockClientId(); - const selectedBlockClientIds = selectedBlockClientId ? [ selectedBlockClientId ] : getMultiSelectedBlockClientIds(); + const selectedBlockClientIds = getSelectedBlockClientIds(); return { rootBlocksClientIds: getBlockOrder(), diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index 9c3e5b7b707ff5..1c6a1fd5a3770f 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -18,8 +18,6 @@ import { withDispatch } from '@wordpress/data'; import { shortcuts } from '../block-editor-keyboard-shortcuts'; import BlockActions from '../block-actions'; import BlockModeToggle from './block-mode-toggle'; -import ReusableBlockConvertButton from './reusable-block-convert-button'; -import ReusableBlockDeleteButton from './reusable-block-delete-button'; import BlockHTMLConvertButton from './block-html-convert-button'; import BlockUnknownConvertButton from './block-unknown-convert-button'; import _BlockSettingsMenuFirstItem from './block-settings-menu-first-item'; @@ -106,18 +104,8 @@ export function BlockSettingsMenu( { clientIds, onSelect } ) { onToggle={ onClose } /> ) } - <_BlockSettingsMenuPluginsExtension.Slot fillProps={ { clientIds, onClose } } />
- { count === 1 && ( - - ) } { ! isLocked && ( { const { - getSelectedBlockClientId, getBlockMode, - getMultiSelectedBlockClientIds, + getSelectedBlockClientIds, isBlockValid, } = select( 'core/block-editor' ); - const selectedBlockClientId = getSelectedBlockClientId(); - const blockClientIds = selectedBlockClientId ? - [ selectedBlockClientId ] : - getMultiSelectedBlockClientIds(); + const blockClientIds = getSelectedBlockClientIds(); return { blockClientIds, - isValid: selectedBlockClientId ? isBlockValid( selectedBlockClientId ) : null, - mode: selectedBlockClientId ? getBlockMode( selectedBlockClientId ) : null, + isValid: blockClientIds.length === 1 ? isBlockValid( blockClientIds[ 0 ] ) : null, + mode: blockClientIds.length === 1 ? getBlockMode( blockClientIds[ 0 ] ) : null, }; } )( BlockToolbar ); diff --git a/packages/block-editor/src/components/copy-handler/index.js b/packages/block-editor/src/components/copy-handler/index.js index 3f73d5f672c153..75b2db4098858e 100644 --- a/packages/block-editor/src/components/copy-handler/index.js +++ b/packages/block-editor/src/components/copy-handler/index.js @@ -18,16 +18,13 @@ export default compose( [ withDispatch( ( dispatch, ownProps, { select } ) => { const { getBlocksByClientId, - getMultiSelectedBlockClientIds, - getSelectedBlockClientId, + getSelectedBlockClientIds, hasMultiSelection, } = select( 'core/block-editor' ); const { removeBlocks } = dispatch( 'core/block-editor' ); const onCopy = ( event ) => { - const selectedBlockClientIds = getSelectedBlockClientId() ? - [ getSelectedBlockClientId() ] : - getMultiSelectedBlockClientIds(); + const selectedBlockClientIds = getSelectedBlockClientIds(); if ( selectedBlockClientIds.length === 0 ) { return; @@ -52,9 +49,7 @@ export default compose( [ onCopy( event ); if ( hasMultiSelection() ) { - const selectedBlockClientIds = getSelectedBlockClientId() ? - [ getSelectedBlockClientId() ] : - getMultiSelectedBlockClientIds(); + const selectedBlockClientIds = getSelectedBlockClientIds(); removeBlocks( selectedBlockClientIds ); } diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d1b142530cff67..51eab010274da0 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -560,18 +560,18 @@ export function getSelectedBlocksInitialCaretPosition( state ) { } /** - * Returns the current multi-selection set of block client IDs, or an empty - * array if there is no multi-selection. + * Returns the current selection set of block client IDs (multiselection or single selection). * * @param {Object} state Editor state. * * @return {Array} Multi-selected block client IDs. */ -export const getMultiSelectedBlockClientIds = createSelector( +export const getSelectedBlockClientIds = createSelector( ( state ) => { const { start, end } = state.blockSelection; if ( start === end ) { - return []; + const selectedBlockClientId = getSelectedBlockClientId( state ); + return selectedBlockClientId ? [ selectedBlockClientId ] : []; } // Retrieve root client ID to aid in retrieving relevant nested block @@ -599,6 +599,23 @@ export const getMultiSelectedBlockClientIds = createSelector( ], ); +/** + * Returns the current multi-selection set of block client IDs, or an empty + * array if there is no multi-selection. + * + * @param {Object} state Editor state. + * + * @return {Array} Multi-selected block client IDs. + */ +export function getMultiSelectedBlockClientIds( state ) { + const { start, end } = state.blockSelection; + if ( start === end ) { + return EMPTY_ARRAY; + } + + return getSelectedBlockClientIds( state ); +} + /** * Returns the current multi-selection set of blocks, or an empty array if * there is no multi-selection. @@ -617,7 +634,7 @@ export const getMultiSelectedBlocks = createSelector( return multiSelectedBlockClientIds.map( ( clientId ) => getBlock( state, clientId ) ); }, ( state ) => [ - ...getMultiSelectedBlockClientIds.getDependants( state ), + ...getSelectedBlockClientIds.getDependants( state ), state.blocks.byClientId, state.blocks.order, state.blocks.attributes, diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 24ae2e643d4c69..399516dde7bd19 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -21,6 +21,7 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import transformStyles from '../../editor-styles'; import { mediaUpload } from '../../utils'; +import ReusableBlocksButtons from '../reusable-blocks-buttons'; const fetchLinkSuggestions = async ( search ) => { const posts = await apiFetch( { @@ -154,6 +155,7 @@ class EditorProvider extends Component { settings={ editorSettings } > { children } + ); } diff --git a/packages/editor/src/components/reusable-blocks-buttons/index.js b/packages/editor/src/components/reusable-blocks-buttons/index.js new file mode 100644 index 00000000000000..4aea20807e2e9b --- /dev/null +++ b/packages/editor/src/components/reusable-blocks-buttons/index.js @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { Fragment } from '@wordpress/element'; +import { _BlockSettingsMenuPluginsExtension } from '@wordpress/block-editor'; +import { withSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import ReusableBlockConvertButton from './reusable-block-convert-button'; +import ReusableBlockDeleteButton from './reusable-block-delete-button'; + +function ReusableBlocksButtons( { clientIds } ) { + return ( + <_BlockSettingsMenuPluginsExtension> + { ( { onClose } ) => ( + + + { clientIds.length === 1 && ( + + ) } + + ) } + + ); +} + +export default withSelect( ( select ) => { + const { getSelectedBlockClientIds } = select( 'core/block-editor' ); + return { + clientIds: getSelectedBlockClientIds(), + }; +} )( ReusableBlocksButtons ); diff --git a/packages/block-editor/src/components/block-settings-menu/reusable-block-convert-button.js b/packages/editor/src/components/reusable-blocks-buttons/reusable-block-convert-button.js similarity index 100% rename from packages/block-editor/src/components/block-settings-menu/reusable-block-convert-button.js rename to packages/editor/src/components/reusable-blocks-buttons/reusable-block-convert-button.js diff --git a/packages/block-editor/src/components/block-settings-menu/reusable-block-delete-button.js b/packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js similarity index 100% rename from packages/block-editor/src/components/block-settings-menu/reusable-block-delete-button.js rename to packages/editor/src/components/reusable-blocks-buttons/reusable-block-delete-button.js From a342b85fe8b3ee0f047b4481cb5f36bff57eac69 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 13 Mar 2019 10:37:43 +0100 Subject: [PATCH 2/5] Fix unit tests --- .../test/__snapshots__/reusable-block-delete-button.js.snap | 0 .../test/reusable-block-convert-button.js | 0 .../reusable-blocks-buttons}/test/reusable-block-delete-button.js | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/{block-editor/src/components/block-settings-menu => editor/src/components/reusable-blocks-buttons}/test/__snapshots__/reusable-block-delete-button.js.snap (100%) rename packages/{block-editor/src/components/block-settings-menu => editor/src/components/reusable-blocks-buttons}/test/reusable-block-convert-button.js (100%) rename packages/{block-editor/src/components/block-settings-menu => editor/src/components/reusable-blocks-buttons}/test/reusable-block-delete-button.js (100%) diff --git a/packages/block-editor/src/components/block-settings-menu/test/__snapshots__/reusable-block-delete-button.js.snap b/packages/editor/src/components/reusable-blocks-buttons/test/__snapshots__/reusable-block-delete-button.js.snap similarity index 100% rename from packages/block-editor/src/components/block-settings-menu/test/__snapshots__/reusable-block-delete-button.js.snap rename to packages/editor/src/components/reusable-blocks-buttons/test/__snapshots__/reusable-block-delete-button.js.snap diff --git a/packages/block-editor/src/components/block-settings-menu/test/reusable-block-convert-button.js b/packages/editor/src/components/reusable-blocks-buttons/test/reusable-block-convert-button.js similarity index 100% rename from packages/block-editor/src/components/block-settings-menu/test/reusable-block-convert-button.js rename to packages/editor/src/components/reusable-blocks-buttons/test/reusable-block-convert-button.js diff --git a/packages/block-editor/src/components/block-settings-menu/test/reusable-block-delete-button.js b/packages/editor/src/components/reusable-blocks-buttons/test/reusable-block-delete-button.js similarity index 100% rename from packages/block-editor/src/components/block-settings-menu/test/reusable-block-delete-button.js rename to packages/editor/src/components/reusable-blocks-buttons/test/reusable-block-delete-button.js From c6854a06b009f0ee897154d9d1501a92ad0b5459 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 26 Mar 2019 09:00:26 +0100 Subject: [PATCH 3/5] Tweaks to the selectors based on the reviews --- packages/block-editor/src/store/selectors.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 51eab010274da0..03f02965457099 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -569,9 +569,12 @@ export function getSelectedBlocksInitialCaretPosition( state ) { export const getSelectedBlockClientIds = createSelector( ( state ) => { const { start, end } = state.blockSelection; + if ( start === null || end === null ) { + return EMPTY_ARRAY; + } + if ( start === end ) { - const selectedBlockClientId = getSelectedBlockClientId( state ); - return selectedBlockClientId ? [ selectedBlockClientId ] : []; + return [ start ]; } // Retrieve root client ID to aid in retrieving relevant nested block @@ -579,7 +582,7 @@ export const getSelectedBlockClientIds = createSelector( // by explicitly testing against null. const rootClientId = getBlockRootClientId( state, start ); if ( rootClientId === null ) { - return []; + return EMPTY_ARRAY; } const blockOrder = getBlockOrder( state, rootClientId ); From 4501badf7b09a997665f92abb27f3e108ee5be0e Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 26 Mar 2019 09:03:02 +0100 Subject: [PATCH 4/5] rename experimental slots using our code convention --- packages/block-editor/README.md | 12 ------------ .../block-settings-menu-first-item.js | 6 +++--- .../block-settings-menu-plugins-extension.js | 6 +++--- .../src/components/block-settings-menu/index.js | 8 ++++---- packages/block-editor/src/components/index.js | 4 ++-- .../edit-post/src/components/visual-editor/index.js | 12 ++++++------ .../src/components/reusable-blocks-buttons/index.js | 6 +++--- 7 files changed, 21 insertions(+), 33 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2543c7affed416..b30502aaf65405 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -520,18 +520,6 @@ font size value retrieval, and font size change handling. Undocumented declaration. -### \_BlockSettingsMenuFirstItem - -[src/index.js#L15-L15](src/index.js#L15-L15) - -Undocumented declaration. - -### \_BlockSettingsMenuPluginsExtension - -[src/index.js#L15-L15](src/index.js#L15-L15) - -Undocumented declaration. - diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-menu-first-item.js b/packages/block-editor/src/components/block-settings-menu/block-settings-menu-first-item.js index ffae5175cb462e..e01f943684ffe9 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-menu-first-item.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-menu-first-item.js @@ -3,8 +3,8 @@ */ import { createSlotFill } from '@wordpress/components'; -const { Fill: _BlockSettingsMenuFirstItem, Slot } = createSlotFill( '_BlockSettingsMenuFirstItem' ); +const { Fill: __experimentalBlockSettingsMenuFirstItem, Slot } = createSlotFill( '__experimentalBlockSettingsMenuFirstItem' ); -_BlockSettingsMenuFirstItem.Slot = Slot; +__experimentalBlockSettingsMenuFirstItem.Slot = Slot; -export default _BlockSettingsMenuFirstItem; +export default __experimentalBlockSettingsMenuFirstItem; diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-menu-plugins-extension.js b/packages/block-editor/src/components/block-settings-menu/block-settings-menu-plugins-extension.js index 3357a6592fe0f4..a750b5b36cc185 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-menu-plugins-extension.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-menu-plugins-extension.js @@ -3,8 +3,8 @@ */ import { createSlotFill } from '@wordpress/components'; -const { Fill: _BlockSettingsMenuPluginsExtension, Slot } = createSlotFill( '_BlockSettingsMenuPluginsExtension' ); +const { Fill: __experimentalBlockSettingsMenuPluginsExtension, Slot } = createSlotFill( '__experimentalBlockSettingsMenuPluginsExtension' ); -_BlockSettingsMenuPluginsExtension.Slot = Slot; +__experimentalBlockSettingsMenuPluginsExtension.Slot = Slot; -export default _BlockSettingsMenuPluginsExtension; +export default __experimentalBlockSettingsMenuPluginsExtension; diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index 1c6a1fd5a3770f..05c023ac43b906 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -20,8 +20,8 @@ import BlockActions from '../block-actions'; import BlockModeToggle from './block-mode-toggle'; import BlockHTMLConvertButton from './block-html-convert-button'; import BlockUnknownConvertButton from './block-unknown-convert-button'; -import _BlockSettingsMenuFirstItem from './block-settings-menu-first-item'; -import _BlockSettingsMenuPluginsExtension from './block-settings-menu-plugins-extension'; +import __experimentalBlockSettingsMenuFirstItem from './block-settings-menu-first-item'; +import __experimentalBlockSettingsMenuPluginsExtension from './block-settings-menu-plugins-extension'; export function BlockSettingsMenu( { clientIds, onSelect } ) { const blockClientIds = castArray( clientIds ); @@ -57,7 +57,7 @@ export function BlockSettingsMenu( { clientIds, onSelect } ) { } } renderContent={ ( { onClose } ) => ( - <_BlockSettingsMenuFirstItem.Slot fillProps={ { onClose } } /> + <__experimentalBlockSettingsMenuFirstItem.Slot fillProps={ { onClose } } /> { count === 1 && ( ) } - <_BlockSettingsMenuPluginsExtension.Slot fillProps={ { clientIds, onClose } } /> + <__experimentalBlockSettingsMenuPluginsExtension.Slot fillProps={ { clientIds, onClose } } />
{ ! isLocked && ( - <_BlockSettingsMenuFirstItem> + <__experimentalBlockSettingsMenuFirstItem> { ( { onClose } ) => } - - <_BlockSettingsMenuPluginsExtension> + + <__experimentalBlockSettingsMenuPluginsExtension> { ( { clientIds, onClose } ) => } - + ); } diff --git a/packages/editor/src/components/reusable-blocks-buttons/index.js b/packages/editor/src/components/reusable-blocks-buttons/index.js index 4aea20807e2e9b..d5a47844bb33ac 100644 --- a/packages/editor/src/components/reusable-blocks-buttons/index.js +++ b/packages/editor/src/components/reusable-blocks-buttons/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { Fragment } from '@wordpress/element'; -import { _BlockSettingsMenuPluginsExtension } from '@wordpress/block-editor'; +import { __experimentalBlockSettingsMenuPluginsExtension } from '@wordpress/block-editor'; import { withSelect } from '@wordpress/data'; /** @@ -13,7 +13,7 @@ import ReusableBlockDeleteButton from './reusable-block-delete-button'; function ReusableBlocksButtons( { clientIds } ) { return ( - <_BlockSettingsMenuPluginsExtension> + <__experimentalBlockSettingsMenuPluginsExtension> { ( { onClose } ) => ( ) } - + ); } From 1ffcefc136bf0c40dc13e6c77c378540fdae4a7e Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 26 Mar 2019 09:09:07 +0100 Subject: [PATCH 5/5] Add unit tests for getSelectedBlockClientIds --- .../block-editor/src/store/test/selectors.js | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index bcda13ad755ff6..fde8a74fefa91f 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -32,6 +32,7 @@ const { getBlockRootClientId, getBlockHierarchyRootClientId, getGlobalBlockCount, + getSelectedBlockClientIds, getMultiSelectedBlockClientIds, getMultiSelectedBlocks, getMultiSelectedBlocksStartClientId, @@ -984,6 +985,61 @@ describe( 'selectors', () => { } ); } ); + describe( 'getSelectedBlockClientIds', () => { + it( 'should return empty if there is no selection', () => { + const state = { + blocks: { + order: { + '': [ 123, 23 ], + }, + }, + blockSelection: { start: null, end: null }, + }; + + expect( getSelectedBlockClientIds( state ) ).toEqual( [] ); + } ); + + it( 'should return the selected block clientId if there is a selection', () => { + const state = { + blocks: { + order: { + '': [ 5, 4, 3, 2, 1 ], + }, + }, + blockSelection: { start: 2, end: 2 }, + }; + + expect( getSelectedBlockClientIds( state ) ).toEqual( [ 2 ] ); + } ); + + it( 'should return selected block clientIds if there is multi selection', () => { + const state = { + blocks: { + order: { + '': [ 5, 4, 3, 2, 1 ], + }, + }, + blockSelection: { start: 2, end: 4 }, + }; + + expect( getSelectedBlockClientIds( state ) ).toEqual( [ 4, 3, 2 ] ); + } ); + + it( 'should return selected block clientIds if there is multi selection (nested context)', () => { + const state = { + blocks: { + order: { + '': [ 5, 4, 3, 2, 1 ], + 4: [ 9, 8, 7, 6 ], + }, + }, + blockSelection: { start: 7, end: 9 }, + }; + + expect( getSelectedBlockClientIds( state ) ).toEqual( [ 9, 8, 7 ] ); + } ); + } ); + describe( 'getMultiSelectedBlockClientIds', () => { it( 'should return empty if there is no multi selection', () => { const state = {