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 de0ca100dbf512..6d2b1ce547e6ef 100644 --- a/docs/designers-developers/developers/data/data-core-block-editor.md +++ b/docs/designers-developers/developers/data/data-core-block-editor.md @@ -691,7 +691,7 @@ _Returns_ Returns true if the block corresponding to the specified client ID is currently selected but isn't the last of the selected blocks. Here "last" refers to the block sequence in the document, _not_ the sequence of -multi-selection, which is why `state.blocks.selection.end` isn't used. +multi-selection, which is why `state.blockSelection.end` isn't used. _Parameters_ diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index c7d174956619fa..92fe8e5d0cc80b 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -353,8 +353,7 @@ const withBlockCache = ( reducer ) => ( state = {}, action ) => { * Higher-order reducer intended to augment the blocks reducer, assigning an * `isPersistentChange` property value corresponding to whether a change in * state can be considered as persistent. All changes are considered persistent - * except selection changes and updating the same block attribute as the - * previous action. + * except when updating the same block attribute as in the previous action. * * @param {Function} reducer Original reducer function. * @@ -366,24 +365,6 @@ function withPersistentBlockChange( reducer ) { return ( state, action ) => { let nextState = reducer( state, action ); - const selectionActions = new Set( [ - 'SELECTION_CHANGE', - 'TOGGLE_SELECTION', - 'SELECT_BLOCK', - 'MULTI_SELECT', - 'START_MULTI_SELECT', - 'STOP_MULTI_SELECT', - 'CLEAR_SELECTED_BLOCK', - 'RESET_SELECTION', - ] ); - - if ( selectionActions.has( action.type ) ) { - return { - ...nextState, - isPersistentChange: false, - }; - } - const isExplicitPersistentChange = action.type === 'MARK_LAST_CHANGE_AS_PERSISTENT'; // Defer to previous state value (or default) unless changing or @@ -495,12 +476,6 @@ const withInnerBlocksRemoveCascade = ( reducer ) => ( state, action ) => { return reducer( state, action ); }; -const BLOCK_SELECTION_EMPTY_OBJECT = {}; -const BLOCK_SELECTION_INITIAL_STATE = { - start: BLOCK_SELECTION_EMPTY_OBJECT, - end: BLOCK_SELECTION_EMPTY_OBJECT, -}; - /** * Higher-order reducer which targets the combined blocks reducer and handles * the `RESET_BLOCKS` action. When dispatched, this action will replace all @@ -513,39 +488,28 @@ const BLOCK_SELECTION_INITIAL_STATE = { */ const withBlockReset = ( reducer ) => ( state, action ) => { if ( state && action.type === 'RESET_BLOCKS' ) { - const { - blocks, - selectionStart = BLOCK_SELECTION_EMPTY_OBJECT, - selectionEnd = BLOCK_SELECTION_EMPTY_OBJECT, - } = action; - const visibleClientIds = getNestedBlockClientIds( state.order ); return { ...state, byClientId: { ...omit( state.byClientId, visibleClientIds ), - ...getFlattenedBlocksWithoutAttributes( blocks ), + ...getFlattenedBlocksWithoutAttributes( action.blocks ), }, attributes: { ...omit( state.attributes, visibleClientIds ), - ...getFlattenedBlockAttributes( blocks ), + ...getFlattenedBlockAttributes( action.blocks ), }, order: { ...omit( state.order, visibleClientIds ), - ...mapBlockOrder( blocks ), + ...mapBlockOrder( action.blocks ), }, parents: { ...omit( state.parents, visibleClientIds ), - ...mapBlockParents( blocks ), + ...mapBlockParents( action.blocks ), }, cache: { ...omit( state.cache, visibleClientIds ), - ...mapValues( flattenBlocks( blocks ), () => ( {} ) ), - }, - selection: { - ...BLOCK_SELECTION_INITIAL_STATE, - start: selectionStart, - end: selectionEnd, + ...mapValues( flattenBlocks( action.blocks ), () => ( {} ) ), }, }; } @@ -622,99 +586,6 @@ const withSaveReusableBlock = ( reducer ) => ( state, action ) => { return reducer( state, action ); }; -/** - * Reducer returning the block selection's state. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {Object} Updated state. - */ -export function blockSelection( state = BLOCK_SELECTION_INITIAL_STATE, action ) { - switch ( action.type ) { - case 'CLEAR_SELECTED_BLOCK': - return BLOCK_SELECTION_INITIAL_STATE; - case 'MULTI_SELECT': - return { - start: { clientId: action.start }, - end: { clientId: action.end }, - }; - case 'SELECT_BLOCK': - if ( - action.clientId === state.start.clientId && - action.clientId === state.end.clientId - ) { - return state; - } - - return { - initialPosition: action.initialPosition, - start: { clientId: action.clientId }, - end: { clientId: action.clientId }, - }; - case 'REPLACE_INNER_BLOCKS': // REPLACE_INNER_BLOCKS and INSERT_BLOCKS should follow the same logic. - case 'INSERT_BLOCKS': { - if ( action.updateSelection ) { - return { - start: { clientId: action.blocks[ 0 ].clientId }, - end: { clientId: action.blocks[ 0 ].clientId }, - }; - } - - return state; - } - case 'REMOVE_BLOCKS': - if ( - ! action.clientIds || - ! action.clientIds.length || - action.clientIds.indexOf( state.start.clientId ) === -1 - ) { - return state; - } - - return BLOCK_SELECTION_INITIAL_STATE; - case 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN': { - if ( action.clientIds.indexOf( state.start.clientId ) === -1 ) { - return state; - } - - const indexToSelect = action.indexToSelect || action.blocks.length - 1; - const blockToSelect = action.blocks[ indexToSelect ]; - - if ( ! blockToSelect ) { - return BLOCK_SELECTION_INITIAL_STATE; - } - - if ( - blockToSelect.clientId === state.start.clientId && - blockToSelect.clientId === state.end.clientId - ) { - return state; - } - - return { - start: { clientId: blockToSelect.clientId }, - end: { clientId: blockToSelect.clientId }, - }; - } - case 'SELECTION_CHANGE': - return { - start: { - clientId: action.clientId, - attributeKey: action.attributeKey, - offset: action.startOffset, - }, - end: { - clientId: action.clientId, - attributeKey: action.attributeKey, - offset: action.endOffset, - }, - }; - } - - return state; -} - /** * Reducer returning the blocks state. * @@ -1030,8 +901,6 @@ export const blocks = flow( return state; }, - - selection: blockSelection, } ); /** @@ -1074,6 +943,131 @@ export function isCaretWithinFormattedText( state = false, action ) { return state; } +const BLOCK_SELECTION_EMPTY_OBJECT = {}; + +/** + * Reducer returning the block selection's state. + * + * @param {Object} state Current state. + * @param {Object} action Dispatched action. + * + * @return {Object} Updated state. + */ +export function blockSelection( state = { + start: BLOCK_SELECTION_EMPTY_OBJECT, + end: BLOCK_SELECTION_EMPTY_OBJECT, +}, action ) { + switch ( action.type ) { + case 'CLEAR_SELECTED_BLOCK': { + const start = BLOCK_SELECTION_EMPTY_OBJECT; + const end = BLOCK_SELECTION_EMPTY_OBJECT; + + if ( start !== state.start || end !== state.end ) { + return { start, end }; + } + + return state; + } + + case 'MULTI_SELECT': + return { + start: { clientId: action.start }, + end: { clientId: action.end }, + }; + case 'SELECT_BLOCK': + if ( + action.clientId === state.start.clientId && + action.clientId === state.end.clientId + ) { + return state; + } + + return { + initialPosition: action.initialPosition, + start: { clientId: action.clientId }, + end: { clientId: action.clientId }, + }; + case 'REPLACE_INNER_BLOCKS': // REPLACE_INNER_BLOCKS and INSERT_BLOCKS should follow the same logic. + case 'INSERT_BLOCKS': { + if ( action.updateSelection ) { + return { + start: { clientId: action.blocks[ 0 ].clientId }, + end: { clientId: action.blocks[ 0 ].clientId }, + }; + } + + return state; + } + case 'REMOVE_BLOCKS': + if ( + ! action.clientIds || + ! action.clientIds.length || + action.clientIds.indexOf( state.start.clientId ) === -1 + ) { + return state; + } + + return { + start: BLOCK_SELECTION_EMPTY_OBJECT, + end: BLOCK_SELECTION_EMPTY_OBJECT, + }; + case 'REPLACE_BLOCKS': { + if ( action.clientIds.indexOf( state.start.clientId ) === -1 ) { + return state; + } + + const indexToSelect = action.indexToSelect || action.blocks.length - 1; + const blockToSelect = action.blocks[ indexToSelect ]; + + if ( ! blockToSelect ) { + return { + start: BLOCK_SELECTION_EMPTY_OBJECT, + end: BLOCK_SELECTION_EMPTY_OBJECT, + }; + } + + if ( + blockToSelect.clientId === state.start.clientId && + blockToSelect.clientId === state.end.clientId + ) { + return state; + } + + return { + start: { clientId: blockToSelect.clientId }, + end: { clientId: blockToSelect.clientId }, + }; + } + case 'SELECTION_CHANGE': + return { + start: { + clientId: action.clientId, + attributeKey: action.attributeKey, + offset: action.startOffset, + }, + end: { + clientId: action.clientId, + attributeKey: action.attributeKey, + offset: action.endOffset, + }, + }; + case 'RESET_BLOCKS': { + const { + selectionStart: start = BLOCK_SELECTION_EMPTY_OBJECT, + selectionEnd: end = BLOCK_SELECTION_EMPTY_OBJECT, + } = action; + + if ( start !== state.start || end !== state.end ) { + return { start, end }; + } + + return state; + } + } + + return state; +} + /** * Reducer returning whether the user is multi-selecting. * @@ -1102,7 +1096,7 @@ export function isMultiSelecting( state = false, action ) { * * @return {boolean} Updated state. */ -export function isSelectionEnabled( state = false, action ) { +export function isSelectionEnabled( state = true, action ) { switch ( action.type ) { case 'TOGGLE_SELECTION': return action.isSelectionEnabled; @@ -1268,6 +1262,9 @@ export default withPostMetaUpdateCacheReset( blocks, isTyping, isCaretWithinFormattedText, + blockSelection, + isMultiSelecting, + isSelectionEnabled, blocksMode, blockListSettings, insertionPoint, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 47b80de9b18d83..1bf27c897aef9b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -332,7 +332,7 @@ export function getBlockCount( state, rootClientId ) { * @return {WPBlockSelection} Selection start information. */ export function getSelectionStart( state ) { - return state.blocks.selection.start; + return state.blockSelection.start; } /** @@ -344,7 +344,7 @@ export function getSelectionStart( state ) { * @return {WPBlockSelection} Selection end information. */ export function getSelectionEnd( state ) { - return state.blocks.selection.end; + return state.blockSelection.end; } /** @@ -357,7 +357,7 @@ export function getSelectionEnd( state ) { * @return {?string} Client ID of block selection start. */ export function getBlockSelectionStart( state ) { - return state.blocks.selection.start.clientId; + return state.blockSelection.start.clientId; } /** @@ -370,7 +370,7 @@ export function getBlockSelectionStart( state ) { * @return {?string} Client ID of block selection end. */ export function getBlockSelectionEnd( state ) { - return state.blocks.selection.end.clientId; + return state.blockSelection.end.clientId; } /** @@ -387,7 +387,7 @@ export function getSelectedBlockCount( state ) { return multiSelectedBlockCount; } - return state.blocks.selection.start.clientId ? 1 : 0; + return state.blockSelection.start.clientId ? 1 : 0; } /** @@ -398,7 +398,7 @@ export function getSelectedBlockCount( state ) { * @return {boolean} Whether a single block is selected. */ export function hasSelectedBlock( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; return !! start.clientId && start.clientId === end.clientId; } @@ -411,7 +411,7 @@ export function hasSelectedBlock( state ) { * @return {?string} Selected block client ID. */ export function getSelectedBlockClientId( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; // We need to check the block exists because the current blockSelection // reducer doesn't take into account when blocks are reset via undo. To be // removed when that's fixed. @@ -563,13 +563,13 @@ export function getNextBlockClientId( state, startClientId ) { * @return {?Object} Selected block. */ export function getSelectedBlocksInitialCaretPosition( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId !== end.clientId || ! start.clientId ) { return null; } - return state.blocks.selection.initialPosition; + return state.blockSelection.initialPosition; } /** @@ -581,7 +581,7 @@ export function getSelectedBlocksInitialCaretPosition( state ) { */ export const getSelectedBlockClientIds = createSelector( ( state ) => { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId === undefined || end.clientId === undefined ) { return EMPTY_ARRAY; @@ -611,8 +611,8 @@ export const getSelectedBlockClientIds = createSelector( }, ( state ) => [ state.blocks.order, - state.blocks.selection.start.clientId, - state.blocks.selection.end.clientId, + state.blockSelection.start.clientId, + state.blockSelection.end.clientId, ], ); @@ -625,7 +625,7 @@ export const getSelectedBlockClientIds = createSelector( * @return {Array} Multi-selected block client IDs. */ export function getMultiSelectedBlockClientIds( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId === end.clientId ) { return EMPTY_ARRAY; @@ -756,8 +756,8 @@ export const isAncestorMultiSelected = createSelector( }, ( state ) => [ state.blocks.order, - state.blocks.selection.start.clientId, - state.blocks.selection.end.clientId, + state.blockSelection.start.clientId, + state.blockSelection.end.clientId, ], ); /** @@ -773,7 +773,7 @@ export const isAncestorMultiSelected = createSelector( * @return {?string} Client ID of block beginning multi-selection. */ export function getMultiSelectedBlocksStartClientId( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId === end.clientId ) { return null; } @@ -793,7 +793,7 @@ export function getMultiSelectedBlocksStartClientId( state ) { * @return {?string} Client ID of block ending multi-selection. */ export function getMultiSelectedBlocksEndClientId( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId === end.clientId ) { return null; } @@ -838,7 +838,7 @@ export function getBlockIndex( state, clientId, rootClientId ) { * @return {boolean} Whether block is selected and multi-selection exists. */ export function isBlockSelected( state, clientId ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; if ( start.clientId !== end.clientId ) { return false; @@ -871,7 +871,7 @@ export function hasSelectedInnerBlock( state, clientId, deep = false ) { * Returns true if the block corresponding to the specified client ID is * currently selected but isn't the last of the selected blocks. Here "last" * refers to the block sequence in the document, _not_ the sequence of - * multi-selection, which is why `state.blocks.selection.end` isn't used. + * multi-selection, which is why `state.blockSelection.end` isn't used. * * @param {Object} state Editor state. * @param {string} clientId Block client ID. @@ -897,7 +897,7 @@ export function isBlockWithinSelection( state, clientId ) { * @return {boolean} Whether multi-selection has been made. */ export function hasMultiSelection( state ) { - const { start, end } = state.blocks.selection; + const { start, end } = state.blockSelection; return start.clientId !== end.clientId; } @@ -973,12 +973,12 @@ export function isCaretWithinFormattedText( state ) { export function getBlockInsertionPoint( state ) { let rootClientId, index; - const { insertionPoint, blocks } = state; + const { insertionPoint, blockSelection } = state; if ( insertionPoint !== null ) { return insertionPoint; } - const { end } = blocks.selection; + const { end } = blockSelection; if ( end.clientId ) { rootClientId = getBlockRootClientId( state, end.clientId ) || undefined; index = getBlockIndex( state, end.clientId, rootClientId ) + 1; diff --git a/packages/block-editor/src/store/test/effects.js b/packages/block-editor/src/store/test/effects.js index 5c537982f996f2..827dde0d39b5c1 100644 --- a/packages/block-editor/src/store/test/effects.js +++ b/packages/block-editor/src/store/test/effects.js @@ -107,13 +107,11 @@ describe( 'effects', () => { }; const dispatch = jest.fn(); const getState = () => ( { - blocks: { - selection: { - start: { - clientId: blockB.clientId, - attributeKey: 'content', - offset: 0, - }, + blockSelection: { + start: { + clientId: blockB.clientId, + attributeKey: 'content', + offset: 0, }, }, } ); @@ -173,13 +171,11 @@ describe( 'effects', () => { }; const dispatch = jest.fn(); const getState = () => ( { - blocks: { - selection: { - start: { - clientId: blockB.clientId, - attributeKey: 'content', - offset: 0, - }, + blockSelection: { + start: { + clientId: blockB.clientId, + attributeKey: 'content', + offset: 0, }, }, } ); @@ -242,13 +238,11 @@ describe( 'effects', () => { }; const dispatch = jest.fn(); const getState = () => ( { - blocks: { - selection: { - start: { - clientId: blockB.clientId, - attributeKey: 'content2', - offset: 0, - }, + blockSelection: { + start: { + clientId: blockB.clientId, + attributeKey: 'content2', + offset: 0, }, }, } ); diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index 0ea4e8dbf39e58..75602268f34cff 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -21,9 +21,9 @@ import { isUpdatingSameBlockAttribute, blocks, isTyping, - isMultiSelecting, isCaretWithinFormattedText, blockSelection, + isMultiSelecting, preferences, blocksMode, insertionPoint, @@ -276,10 +276,6 @@ describe( 'state', () => { chicken: {}, [ newChildBlockId ]: {}, }, - selection: { - start: {}, - end: {}, - }, } ); expect( state.cache.chicken ).not.toBe( existingState.cache.chicken ); } ); @@ -358,10 +354,6 @@ describe( 'state', () => { chicken: {}, [ newChildBlockId ]: {}, }, - selection: { - start: {}, - end: {}, - }, } ); expect( state.cache.chicken ).not.toBe( existingState.cache.chicken ); } ); @@ -496,10 +488,6 @@ describe( 'state', () => { [ newChildBlockId2 ]: {}, [ newChildBlockId3 ]: {}, }, - selection: { - start: {}, - end: {}, - }, } ); } ); @@ -589,10 +577,6 @@ describe( 'state', () => { chicken: {}, [ newChildBlockId ]: {}, }, - selection: { - start: {}, - end: {}, - }, } ); // the cache key of the parent should be updated @@ -611,10 +595,6 @@ describe( 'state', () => { isPersistentChange: true, isIgnoredChange: false, cache: {}, - selection: { - start: {}, - end: {}, - }, } ); } ); @@ -1814,7 +1794,7 @@ describe( 'state', () => { } ); it( 'should set multi selection', () => { - const original = deepFreeze( {} ); + const original = deepFreeze( { isMultiSelecting: false } ); const state = blockSelection( original, { type: 'MULTI_SELECT', start: 'ribs', @@ -1828,7 +1808,7 @@ describe( 'state', () => { } ); it( 'should set continuous multi selection', () => { - const original = deepFreeze( {} ); + const original = deepFreeze( { isMultiSelecting: true } ); const state = blockSelection( original, { type: 'MULTI_SELECT', start: 'ribs', @@ -1848,7 +1828,6 @@ describe( 'state', () => { expect( state ).toBe( true ); } ); - it( 'should end multi selection with selection', () => { const state = isMultiSelecting( true, { type: 'STOP_MULTI_SELECT', @@ -1940,7 +1919,7 @@ describe( 'state', () => { it( 'should replace the selected block', () => { const original = deepFreeze( { start: { clientId: 'chicken' }, end: { clientId: 'chicken' } } ); const state = blockSelection( original, { - type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN', + type: 'REPLACE_BLOCKS', clientIds: [ 'chicken' ], blocks: [ { clientId: 'wings', @@ -1957,7 +1936,7 @@ describe( 'state', () => { it( 'should not replace the selected block if we keep it at the end when replacing blocks', () => { const original = deepFreeze( { start: { clientId: 'wings' }, end: { clientId: 'wings' } } ); const state = blockSelection( original, { - type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN', + type: 'REPLACE_BLOCKS', clientIds: [ 'wings' ], blocks: [ { @@ -1976,7 +1955,7 @@ describe( 'state', () => { it( 'should replace the selected block if we keep it not at the end when replacing blocks', () => { const original = deepFreeze( { start: { clientId: 'chicken' }, end: { clientId: 'chicken' } } ); const state = blockSelection( original, { - type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN', + type: 'REPLACE_BLOCKS', clientIds: [ 'chicken' ], blocks: [ { @@ -1998,7 +1977,7 @@ describe( 'state', () => { it( 'should reset if replacing with empty set', () => { const original = deepFreeze( { start: { clientId: 'chicken' }, end: { clientId: 'chicken' } } ); const state = blockSelection( original, { - type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN', + type: 'REPLACE_BLOCKS', clientIds: [ 'chicken' ], blocks: [], } ); @@ -2012,7 +1991,7 @@ describe( 'state', () => { it( 'should keep the selected block', () => { const original = deepFreeze( { start: { clientId: 'chicken' }, end: { clientId: 'chicken' } } ); const state = blockSelection( original, { - type: 'REPLACE_BLOCKS_AUGMENTED_WITH_CHILDREN', + type: 'REPLACE_BLOCKS', clientIds: [ 'ribs' ], blocks: [ { clientId: 'wings', diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 66d7e7089d6928..8648bdb7da232d 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -577,11 +577,9 @@ describe( 'selectors', () => { describe( 'hasSelectedBlock', () => { it( 'should return false if no selection', () => { const state = { - blocks: { - selection: { - start: {}, - end: {}, - }, + blockSelection: { + start: {}, + end: {}, }, }; @@ -590,11 +588,9 @@ describe( 'selectors', () => { it( 'should return false if multi-selection', () => { const state = { - blocks: { - selection: { - start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - end: { clientId: '9db792c6-a25a-495d-adbd-97d56a4c4189' }, - }, + blockSelection: { + start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, + end: { clientId: '9db792c6-a25a-495d-adbd-97d56a4c4189' }, }, }; @@ -603,11 +599,9 @@ describe( 'selectors', () => { it( 'should return true if singular selection', () => { const state = { - blocks: { - selection: { - start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - end: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - }, + blockSelection: { + start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, + end: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, }, }; @@ -663,7 +657,7 @@ describe( 'selectors', () => { describe( 'getSelectedBlockClientId', () => { it( 'should return null if no block is selected', () => { const state = { - blocks: { selection: { start: {}, end: {} } }, + blockSelection: { start: {}, end: {} }, }; expect( getSelectedBlockClientId( state ) ).toBe( null ); @@ -671,7 +665,7 @@ describe( 'selectors', () => { it( 'should return null if there is multi selection', () => { const state = { - blocks: { selection: { start: { clientId: 23 }, end: { clientId: 123 } } }, + blockSelection: { start: { clientId: 23 }, end: { clientId: 123 } }, }; expect( getSelectedBlockClientId( state ) ).toBe( null ); @@ -685,8 +679,8 @@ describe( 'selectors', () => { name: 'fake block', }, }, - selection: { start: { clientId: 23 }, end: { clientId: 23 } }, }, + blockSelection: { start: { clientId: 23 }, end: { clientId: 23 } }, }; expect( getSelectedBlockClientId( state ) ).toEqual( 23 ); @@ -714,8 +708,8 @@ describe( 'selectors', () => { 23: '', 123: '', }, - selection: { start: {}, end: {} }, }, + blockSelection: { start: {}, end: {} }, }; expect( getSelectedBlock( state ) ).toBe( null ); @@ -741,8 +735,8 @@ describe( 'selectors', () => { 123: '', 23: '', }, - selection: { start: { clientId: 23 }, end: { clientId: 123 } }, }, + blockSelection: { start: { clientId: 23 }, end: { clientId: 123 } }, }; expect( getSelectedBlock( state ) ).toBe( null ); @@ -771,8 +765,8 @@ describe( 'selectors', () => { cache: { 23: {}, }, - selection: { start: { clientId: 23 }, end: { clientId: 23 } }, }, + blockSelection: { start: { clientId: 23 }, end: { clientId: 23 } }, }; expect( getSelectedBlock( state ) ).toEqual( { @@ -880,8 +874,8 @@ describe( 'selectors', () => { 123: '', 23: '', }, - selection: { start: {}, end: {} }, }, + blockSelection: { start: {}, end: {} }, }; expect( getSelectedBlockClientIds( state ) ).toEqual( [] ); @@ -900,8 +894,8 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 2 }, end: { clientId: 2 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 2 } }, }; expect( getSelectedBlockClientIds( state ) ).toEqual( [ 2 ] ); @@ -920,8 +914,8 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 2 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; expect( getSelectedBlockClientIds( state ) ).toEqual( [ 4, 3, 2 ] ); @@ -945,8 +939,8 @@ describe( 'selectors', () => { 8: 4, 9: 4, }, - selection: { start: { clientId: 7 }, end: { clientId: 9 } }, }, + blockSelection: { start: { clientId: 7 }, end: { clientId: 9 } }, }; expect( getSelectedBlockClientIds( state ) ).toEqual( [ 9, 8, 7 ] ); @@ -964,8 +958,8 @@ describe( 'selectors', () => { 23: '', 123: '', }, - selection: { start: {}, end: {} }, }, + blockSelection: { start: {}, end: {} }, }; expect( getMultiSelectedBlockClientIds( state ) ).toEqual( [] ); @@ -984,8 +978,8 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 2 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; expect( getMultiSelectedBlockClientIds( state ) ).toEqual( [ 4, 3, 2 ] ); @@ -1009,8 +1003,8 @@ describe( 'selectors', () => { 8: 4, 9: 4, }, - selection: { start: { clientId: 7 }, end: { clientId: 9 } }, }, + blockSelection: { start: { clientId: 7 }, end: { clientId: 9 } }, }; expect( getMultiSelectedBlockClientIds( state ) ).toEqual( [ 9, 8, 7 ] ); @@ -1025,8 +1019,8 @@ describe( 'selectors', () => { attributes: {}, order: {}, parents: {}, - selection: { start: {}, end: {} }, }, + blockSelection: { start: {}, end: {} }, }; expect( @@ -1038,7 +1032,7 @@ describe( 'selectors', () => { describe( 'getMultiSelectedBlocksStartClientId', () => { it( 'returns null if there is no multi selection', () => { const state = { - blocks: { selection: { start: {}, end: {} } }, + blockSelection: { start: {}, end: {} }, }; expect( getMultiSelectedBlocksStartClientId( state ) ).toBeNull(); @@ -1046,7 +1040,7 @@ describe( 'selectors', () => { it( 'returns multi selection start', () => { const state = { - blocks: { selection: { start: { clientId: 2 }, end: { clientId: 4 } } }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; expect( getMultiSelectedBlocksStartClientId( state ) ).toBe( 2 ); @@ -1056,7 +1050,7 @@ describe( 'selectors', () => { describe( 'getMultiSelectedBlocksEndClientId', () => { it( 'returns null if there is no multi selection', () => { const state = { - blocks: { selection: { start: {}, end: {} } }, + blockSelection: { start: {}, end: {} }, }; expect( getMultiSelectedBlocksEndClientId( state ) ).toBeNull(); @@ -1064,7 +1058,7 @@ describe( 'selectors', () => { it( 'returns multi selection end', () => { const state = { - blocks: { selection: { start: { clientId: 2 }, end: { clientId: 4 } } }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; expect( getMultiSelectedBlocksEndClientId( state ) ).toBe( 4 ); @@ -1291,7 +1285,7 @@ describe( 'selectors', () => { describe( 'isBlockSelected', () => { it( 'should return true if the block is selected', () => { const state = { - blocks: { selection: { start: { clientId: 123 }, end: { clientId: 123 } } }, + blockSelection: { start: { clientId: 123 }, end: { clientId: 123 } }, }; expect( isBlockSelected( state, 123 ) ).toBe( true ); @@ -1299,7 +1293,7 @@ describe( 'selectors', () => { it( 'should return false if a multi-selection range exists', () => { const state = { - blocks: { selection: { start: { clientId: 123 }, end: { clientId: 124 } } }, + blockSelection: { start: { clientId: 123 }, end: { clientId: 124 } }, }; expect( isBlockSelected( state, 123 ) ).toBe( false ); @@ -1307,7 +1301,7 @@ describe( 'selectors', () => { it( 'should return false if the block is not selected', () => { const state = { - blocks: { selection: { start: {}, end: {} } }, + blockSelection: { start: {}, end: {} }, }; expect( isBlockSelected( state, 23 ) ).toBe( false ); @@ -1317,6 +1311,7 @@ describe( 'selectors', () => { describe( 'hasSelectedInnerBlock', () => { it( 'should return false if the selected block is a child of the given ClientId', () => { const state = { + blockSelection: { start: { clientId: 5 }, end: { clientId: 5 } }, blocks: { order: { 4: [ 3, 2, 1 ], @@ -1326,7 +1321,6 @@ describe( 'selectors', () => { 2: 4, 3: 4, }, - selection: { start: { clientId: 5 }, end: { clientId: 5 } }, }, }; @@ -1335,6 +1329,7 @@ describe( 'selectors', () => { it( 'should return true if the selected block is a child of the given ClientId', () => { const state = { + blockSelection: { start: { clientId: 3 }, end: { clientId: 3 } }, blocks: { order: { 4: [ 3, 2, 1 ], @@ -1344,7 +1339,6 @@ describe( 'selectors', () => { 2: 4, 3: 4, }, - selection: { start: { clientId: 3 }, end: { clientId: 3 } }, }, }; @@ -1364,8 +1358,8 @@ describe( 'selectors', () => { 4: 6, 5: 6, }, - selection: { start: { clientId: 2 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; expect( hasSelectedInnerBlock( state, 6 ) ).toBe( true ); } ); @@ -1383,8 +1377,8 @@ describe( 'selectors', () => { 4: 6, 5: 6, }, - selection: { start: { clientId: 5 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 5 }, end: { clientId: 4 } }, }; expect( hasSelectedInnerBlock( state, 3 ) ).toBe( false ); } ); @@ -1393,6 +1387,7 @@ describe( 'selectors', () => { describe( 'isBlockWithinSelection', () => { it( 'should return true if the block is selected but not the last', () => { const state = { + blockSelection: { start: { clientId: 5 }, end: { clientId: 3 } }, blocks: { order: { '': [ 5, 4, 3, 2, 1 ], @@ -1404,7 +1399,6 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 5 }, end: { clientId: 3 } }, }, }; @@ -1413,6 +1407,7 @@ describe( 'selectors', () => { it( 'should return false if the block is the last selected', () => { const state = { + blockSelection: { start: { clientId: 5 }, end: { clientId: 3 } }, blocks: { order: { '': [ 5, 4, 3, 2, 1 ], @@ -1424,7 +1419,6 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 5 }, end: { clientId: 3 } }, }, }; @@ -1433,6 +1427,7 @@ describe( 'selectors', () => { it( 'should return false if the block is not selected', () => { const state = { + blockSelection: { start: { clientId: 5 }, end: { clientId: 3 } }, blocks: { order: { '': [ 5, 4, 3, 2, 1 ], @@ -1444,7 +1439,6 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 5 }, end: { clientId: 3 } }, }, }; @@ -1453,6 +1447,7 @@ describe( 'selectors', () => { it( 'should return false if there is no selection', () => { const state = { + blockSelection: { start: {}, end: {} }, blocks: { order: { '': [ 5, 4, 3, 2, 1 ], @@ -1464,7 +1459,6 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: {}, end: {} }, }, }; @@ -1475,7 +1469,10 @@ describe( 'selectors', () => { describe( 'hasMultiSelection', () => { it( 'should return false if no selection', () => { const state = { - blocks: { selection: { start: {}, end: {} } }, + blockSelection: { + start: {}, + end: {}, + }, }; expect( hasMultiSelection( state ) ).toBe( false ); @@ -1483,11 +1480,9 @@ describe( 'selectors', () => { it( 'should return false if singular selection', () => { const state = { - blocks: { - selection: { - start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - end: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - }, + blockSelection: { + start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, + end: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, }, }; @@ -1496,11 +1491,9 @@ describe( 'selectors', () => { it( 'should return true if multi-selection', () => { const state = { - blocks: { - selection: { - start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, - end: { clientId: '9db792c6-a25a-495d-adbd-97d56a4c4189' }, - }, + blockSelection: { + start: { clientId: 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' }, + end: { clientId: '9db792c6-a25a-495d-adbd-97d56a4c4189' }, }, }; @@ -1521,8 +1514,8 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 2 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; it( 'should return true if the block is multi selected', () => { @@ -1547,8 +1540,8 @@ describe( 'selectors', () => { 4: '', 5: '', }, - selection: { start: { clientId: 2 }, end: { clientId: 4 } }, }, + blockSelection: { start: { clientId: 2 }, end: { clientId: 4 } }, }; it( 'should return true if the block is first in multi selection', () => { @@ -1637,6 +1630,10 @@ describe( 'selectors', () => { describe( 'getBlockInsertionPoint', () => { it( 'should return the explicitly assigned insertion point', () => { const state = { + blockSelection: { + start: { clientId: 'clientId2' }, + end: { clientId: 'clientId2' }, + }, blocks: { byClientId: { clientId1: { clientId: 'clientId1' }, @@ -1655,10 +1652,6 @@ describe( 'selectors', () => { clientId1: '', clientId2: 'clientId1', }, - selection: { - start: { clientId: 'clientId2' }, - end: { clientId: 'clientId2' }, - }, }, insertionPoint: { rootClientId: undefined, @@ -1674,6 +1667,10 @@ describe( 'selectors', () => { it( 'should return an object for the selected block', () => { const state = { + blockSelection: { + start: { clientId: 'clientId1' }, + end: { clientId: 'clientId1' }, + }, blocks: { byClientId: { clientId1: { clientId: 'clientId1' }, @@ -1688,10 +1685,6 @@ describe( 'selectors', () => { parents: { clientId1: '', }, - selection: { - start: { clientId: 'clientId1' }, - end: { clientId: 'clientId1' }, - }, }, insertionPoint: null, }; @@ -1704,6 +1697,10 @@ describe( 'selectors', () => { it( 'should return an object for the nested selected block', () => { const state = { + blockSelection: { + start: { clientId: 'clientId2' }, + end: { clientId: 'clientId2' }, + }, blocks: { byClientId: { clientId1: { clientId: 'clientId1' }, @@ -1722,10 +1719,6 @@ describe( 'selectors', () => { clientId1: '', clientId2: 'clientId1', }, - selection: { - start: { clientId: 'clientId2' }, - end: { clientId: 'clientId2' }, - }, }, insertionPoint: null, }; @@ -1738,6 +1731,10 @@ describe( 'selectors', () => { it( 'should return an object for the last multi selected clientId', () => { const state = { + blockSelection: { + start: { clientId: 'clientId1' }, + end: { clientId: 'clientId2' }, + }, blocks: { byClientId: { clientId1: { clientId: 'clientId1' }, @@ -1756,10 +1753,6 @@ describe( 'selectors', () => { clientId1: '', clientId2: '', }, - selection: { - start: { clientId: 'clientId1' }, - end: { clientId: 'clientId2' }, - }, }, insertionPoint: null, }; @@ -1772,6 +1765,10 @@ describe( 'selectors', () => { it( 'should return an object for the last block if no selection', () => { const state = { + blockSelection: { + start: {}, + end: {}, + }, blocks: { byClientId: { clientId1: { clientId: 'clientId1' }, @@ -1790,10 +1787,6 @@ describe( 'selectors', () => { clientId1: '', clientId2: '', }, - selection: { - start: {}, - end: {}, - }, }, insertionPoint: null, };