Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to how blocks with a 'disabled' editing mode behave #51148

Merged
merged 2 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getDefaultBlockName } from '@wordpress/blocks';
import DefaultBlockAppender from '../default-block-appender';
import ButtonBlockAppender from '../button-block-appender';
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

function DefaultAppender( { rootClientId } ) {
const canInsertDefaultBlock = useSelect( ( select ) =>
Expand Down Expand Up @@ -46,13 +47,15 @@ function useAppender( rootClientId, CustomAppender ) {
getTemplateLock,
getSelectedBlockClientId,
__unstableGetEditorMode,
} = select( blockEditorStore );
getBlockEditingMode,
} = unlock( select( blockEditorStore ) );

const selectedBlockClientId = getSelectedBlockClientId();

return {
hideInserter:
!! getTemplateLock( rootClientId ) ||
getBlockEditingMode( rootClientId ) === 'disabled' ||
__unstableGetEditorMode() === 'zoom-out',
isParentSelected:
rootClientId === selectedBlockClientId ||
Expand Down
20 changes: 8 additions & 12 deletions packages/block-editor/src/components/block-list/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,6 @@
padding: 0;
}

.block-editor-block-list__layout,
.block-editor-block-list__block {
pointer-events: initial;

&.is-editing-disabled {
pointer-events: none;
}
}

.block-editor-block-list__layout .block-editor-block-list__block {
// With `position: static`, Safari marks a full-width selection rectangle, including margins.
// With `position: relative`, Safari marks an inline selection rectangle, similar to that of
Expand All @@ -178,12 +169,17 @@
// We choose relative, as that matches the multi-selection, which is limited to the block footprint.
position: relative;

// Re-enable text-selection on editable blocks.
user-select: text;

// Break long strings of text without spaces so they don't overflow the block.
overflow-wrap: break-word;

pointer-events: auto;
user-select: text;

&.is-editing-disabled {
pointer-events: none;
user-select: none;
}

.reusable-block-edit-panel * {
z-index: z-index(".block-editor-block-list__block .reusable-block-edit-panel *");
}
Expand Down
58 changes: 28 additions & 30 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import createSelector from 'rememo';
/**
* WordPress dependencies
*/
import { createRegistrySelector } from '@wordpress/data';
import { select } from '@wordpress/data';
import { store as blocksStore } from '@wordpress/blocks';

/**
Expand Down Expand Up @@ -72,35 +72,33 @@ export function getLastInsertedBlocksClientIds( state ) {
* @return {BlockEditingMode} The block editing mode. One of `'disabled'`,
* `'contentOnly'`, or `'default'`.
*/
export const getBlockEditingMode = createRegistrySelector(
( select ) =>
( state, clientId = '' ) => {
const explicitEditingMode = getExplicitBlockEditingMode(
state,
clientId
);
const rootClientId = getBlockRootClientId( state, clientId );
const templateLock = getTemplateLock( state, rootClientId );
const name = getBlockName( state, clientId );
const isContent =
select( blocksStore ).__experimentalHasContentRoleAttribute(
name
);
if (
explicitEditingMode === 'disabled' ||
( templateLock === 'contentOnly' && ! isContent )
) {
return 'disabled';
}
if (
explicitEditingMode === 'contentOnly' ||
( templateLock === 'contentOnly' && isContent )
) {
return 'contentOnly';
}
return 'default';
}
);
export const getBlockEditingMode = ( state, clientId = '' ) => {
const explicitEditingMode = getExplicitBlockEditingMode( state, clientId );
const rootClientId = getBlockRootClientId( state, clientId );
const templateLock = getTemplateLock( state, rootClientId );
const name = getBlockName( state, clientId );
// TODO: Terrible hack! We're calling the global select() function here
// instead of using createRegistrySelector(). The problem with using
// createRegistrySelector() is that then the public block-editor selectors
// (e.g. canInsertBlockTypeUnmemoized) can't call this private block-editor
// selector due to a bug in @wordpress/data. See
// https://github.com/WordPress/gutenberg/pull/50985.
const isContent =
select( blocksStore ).__experimentalHasContentRoleAttribute( name );
if (
explicitEditingMode === 'disabled' ||
( templateLock === 'contentOnly' && ! isContent )
) {
return 'disabled';
}
if (
explicitEditingMode === 'contentOnly' ||
( templateLock === 'contentOnly' && isContent )
) {
return 'contentOnly';
}
return 'default';
};

const getExplicitBlockEditingMode = createSelector(
( state, clientId = '' ) => {
Expand Down
51 changes: 31 additions & 20 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import deprecated from '@wordpress/deprecated';
*/
import { mapRichTextSettings } from './utils';
import { orderBy } from '../utils/sorting';
import { getBlockEditingMode } from './private-selectors';

/**
* A block selection object.
Expand Down Expand Up @@ -1539,6 +1540,10 @@ const canInsertBlockTypeUnmemoized = (
return false;
}

if ( getBlockEditingMode( state, rootClientId ?? '' ) === 'disabled' ) {
return false;
}

const parentBlockListSettings = getBlockListSettings( state, rootClientId );

// The parent block doesn't have settings indicating it doesn't support
Expand Down Expand Up @@ -1633,6 +1638,7 @@ export const canInsertBlockType = createSelector(
state.blocks.byClientId.get( rootClientId ),
state.settings.allowedBlockTypes,
state.settings.templateLock,
state.blockEditingModes,
]
);

Expand Down Expand Up @@ -1663,21 +1669,19 @@ export function canInsertBlocks( state, clientIds, rootClientId = null ) {
*/
export function canRemoveBlock( state, clientId, rootClientId = null ) {
const attributes = getBlockAttributes( state, clientId );

// attributes can be null if the block is already deleted.
if ( attributes === null ) {
return true;
}

const { lock } = attributes;
const parentIsLocked = !! getTemplateLock( state, rootClientId );
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
if ( lock === undefined || lock?.remove === undefined ) {
return ! parentIsLocked;
if ( attributes.lock?.remove ) {
return false;
}

// When remove is true, it means we cannot remove it.
return ! lock?.remove;
if ( getTemplateLock( state, rootClientId ) ) {
return false;
}
if ( getBlockEditingMode( state, rootClientId ) === 'disabled' ) {
return false;
}
return true;
}

/**
Expand Down Expand Up @@ -1709,16 +1713,16 @@ export function canMoveBlock( state, clientId, rootClientId = null ) {
if ( attributes === null ) {
return;
}

const { lock } = attributes;
const parentIsLocked = getTemplateLock( state, rootClientId ) === 'all';
// If we don't have a lock on the blockType level, we defer to the parent templateLock.
if ( lock === undefined || lock?.move === undefined ) {
return ! parentIsLocked;
if ( attributes.lock?.move ) {
return false;
}

// When move is true, it means we cannot move it.
return ! lock?.move;
if ( getTemplateLock( state, rootClientId ) === 'all' ) {
return false;
}
if ( getBlockEditingMode( state, rootClientId ) === 'disabled' ) {
return false;
}
return true;
}

/**
Expand Down Expand Up @@ -2812,6 +2816,13 @@ export function __unstableGetTemporarilyEditingAsBlocks( state ) {
}

export function __unstableHasActiveBlockOverlayActive( state, clientId ) {
// Prevent overlay on disabled blocks. It's redundant since disabled blocks
// can't be selected, and prevents non-disabled nested blocks from being
// selected.
if ( getBlockEditingMode( state, clientId ) === 'disabled' ) {
return false;
}

// If the block editing is locked, the block overlay is always active.
if ( ! canEditBlock( state, clientId ) ) {
return true;
Expand Down
17 changes: 12 additions & 5 deletions packages/block-editor/src/store/test/private-selectors.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* WordPress dependencies
*/
import { select } from '@wordpress/data';

/**
* Internal dependencies
*/
Expand All @@ -8,6 +13,10 @@ import {
isBlockSubtreeDisabled,
} from '../private-selectors';

jest.mock( '@wordpress/data/src/select', () => ( {
select: jest.fn(),
} ) );

describe( 'private selectors', () => {
describe( 'isBlockInterfaceHidden', () => {
it( 'should return the true if toggled true in state', () => {
Expand Down Expand Up @@ -117,11 +126,9 @@ describe( 'private selectors', () => {
const __experimentalHasContentRoleAttribute = jest.fn(
() => false
);
getBlockEditingMode.registry = {
select: jest.fn( () => ( {
__experimentalHasContentRoleAttribute,
} ) ),
};
select.mockReturnValue( {
__experimentalHasContentRoleAttribute,
} );

it( 'should return default by default', () => {
expect(
Expand Down
Loading