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

Template Parts: allow selection in page content focus mode #60010

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/reference-guides/data/data-core-editor.md
Expand Up @@ -1415,7 +1415,6 @@ _Returns_

Returns an action used to set the rendering mode of the post editor. We support multiple rendering modes:

- `all`: This is the default mode. It renders the post editor with all the features available. If a template is provided, it's preferred over the post.
- `post-only`: This mode extracts the post blocks from the template and renders only those. The idea is to allow the user to edit the post/page in isolation without the wrapping template.
- `template-locked`: This mode renders both the template and the post blocks but the template blocks are locked and can't be edited. The post blocks are editable.

Expand Down
Expand Up @@ -160,7 +160,7 @@ function BlockSwitcherDropdownMenuContents( {
);
}

export const BlockSwitcher = ( { clientIds } ) => {
export const BlockSwitcher = ( { clientIds, disabled } ) => {
const {
canRemove,
hasBlockStyles,
Expand Down Expand Up @@ -229,8 +229,8 @@ export const BlockSwitcher = ( { clientIds } ) => {
const blockSwitcherLabel = isSingleBlock
? blockTitle
: __( 'Multiple blocks selected' );
const hideDropdown = ! hasBlockStyles && ! canRemove;

const hideDropdown = disabled || ( ! hasBlockStyles && ! canRemove );
if ( hideDropdown ) {
return (
<ToolbarGroup>
Expand Down
41 changes: 22 additions & 19 deletions packages/block-editor/src/components/block-toolbar/index.js
Expand Up @@ -170,26 +170,29 @@ export function PrivateBlockToolbar( {
{ isUsingBindings && canBindBlock( blockName ) && (
<BlockBindingsIndicator />
) }
{ ( shouldShowVisualToolbar || isMultiToolbar ) &&
isDefaultEditingMode && (
retrofox marked this conversation as resolved.
Show resolved Hide resolved
<div
ref={ nodeRef }
{ ...showHoveredOrFocusedGestures }
>
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
<BlockSwitcher clientIds={ blockClientIds } />
{ ! isMultiToolbar && (
<BlockLockToolbar
clientId={ blockClientId }
{ ( shouldShowVisualToolbar || isMultiToolbar ) && (
<div ref={ nodeRef } { ...showHoveredOrFocusedGestures }>
<ToolbarGroup className="block-editor-block-toolbar__block-controls">
<BlockSwitcher
clientIds={ blockClientIds }
disabled={ ! isDefaultEditingMode }
/>
{ isDefaultEditingMode && (
<>
{ ! isMultiToolbar && (
<BlockLockToolbar
clientId={ blockClientId }
/>
) }
<BlockMover
clientIds={ blockClientIds }
hideDragHandle={ hideDragHandle }
/>
) }
<BlockMover
clientIds={ blockClientIds }
hideDragHandle={ hideDragHandle }
/>
</ToolbarGroup>
</div>
) }
</>
) }
</ToolbarGroup>
</div>
) }
<Shuffle clientId={ blockClientId } />
{ shouldShowVisualToolbar && isMultiToolbar && (
<BlockGroupToolbar />
Expand Down
35 changes: 32 additions & 3 deletions packages/block-library/src/template-part/edit/index.js
Expand Up @@ -11,8 +11,15 @@ import {
useHasRecursion,
InspectorControls,
__experimentalBlockPatternsList as BlockPatternsList,
BlockControls,
} from '@wordpress/block-editor';
import { PanelBody, Spinner, Modal, MenuItem } from '@wordpress/components';
import {
PanelBody,
Spinner,
Modal,
MenuItem,
ToolbarButton,
} from '@wordpress/components';
import { useAsyncList } from '@wordpress/compose';
import { __, sprintf } from '@wordpress/i18n';
import { store as coreStore } from '@wordpress/core-data';
Expand Down Expand Up @@ -104,11 +111,17 @@ export default function TemplatePartEdit( {
const [ isTemplatePartSelectionOpen, setIsTemplatePartSelectionOpen ] =
useState( false );

const { isResolved, hasInnerBlocks, isMissing, area } = useSelect(
const {
isResolved,
hasInnerBlocks,
isMissing,
area,
onNavigateToEntityRecord,
} = useSelect(
( select ) => {
const { getEditedEntityRecord, hasFinishedResolution } =
select( coreStore );
const { getBlockCount } = select( blockEditorStore );
const { getBlockCount, getSettings } = select( blockEditorStore );

const getEntityArgs = [
'postType',
Expand All @@ -134,6 +147,8 @@ export default function TemplatePartEdit( {
( ! entityRecord ||
Object.keys( entityRecord ).length === 0 ),
area: _area,
onNavigateToEntityRecord:
getSettings().onNavigateToEntityRecord,
};
},
[ templatePartId, attributes.area, clientId ]
Expand Down Expand Up @@ -217,6 +232,20 @@ export default function TemplatePartEdit( {
return (
<>
<RecursionProvider uniqueId={ templatePartId }>
{ isEntityAvailable && onNavigateToEntityRecord && (
<BlockControls group="other">
<ToolbarButton
onClick={ () =>
onNavigateToEntityRecord( {
postId: templatePartId,
postType: 'wp_template_part',
} )
}
>
{ __( 'Edit' ) }
</ToolbarButton>
</BlockControls>
) }
<InspectorControls group="advanced">
<TemplatePartAdvancedControls
tagName={ tagName }
Expand Down
39 changes: 28 additions & 11 deletions packages/block-library/src/template-part/edit/inner-blocks.js
Expand Up @@ -7,23 +7,42 @@ import {
useInnerBlocksProps,
useSettings,
store as blockEditorStore,
useBlockEditingMode,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';

function useRenderAppender( hasInnerBlocks ) {
const blockEditingMode = useBlockEditingMode();
// Disable appending when the editing mode is 'contentOnly'. This is so that the user can't
// append into a template part when editing a page in the site editor. See
// DisableNonPageContentBlocks. Ideally instead of (mis)using editing mode there would be a
// block editor API for achieving this.
if ( blockEditingMode === 'contentOnly' ) {
return false;
}
if ( ! hasInnerBlocks ) {
return InnerBlocks.ButtonBlockAppender;
}
}

function useLayout( layout ) {
const themeSupportsLayout = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return getSettings()?.supportsLayout;
}, [] );
const [ defaultLayout ] = useSettings( 'layout' );
if ( themeSupportsLayout ) {
return layout?.inherit ? defaultLayout || {} : layout;
}
}

export default function TemplatePartInnerBlocks( {
postId: id,
hasInnerBlocks,
layout,
tagName: TagName,
blockProps,
} ) {
const themeSupportsLayout = useSelect( ( select ) => {
const { getSettings } = select( blockEditorStore );
return getSettings()?.supportsLayout;
}, [] );
const [ defaultLayout ] = useSettings( 'layout' );
const usedLayout = layout?.inherit ? defaultLayout || {} : layout;

const [ blocks, onInput, onChange ] = useEntityBlockEditor(
'postType',
'wp_template_part',
Expand All @@ -34,10 +53,8 @@ export default function TemplatePartInnerBlocks( {
value: blocks,
onInput,
onChange,
renderAppender: hasInnerBlocks
? undefined
: InnerBlocks.ButtonBlockAppender,
layout: themeSupportsLayout ? usedLayout : undefined,
renderAppender: useRenderAppender( hasInnerBlocks ),
layout: useLayout( layout ),
} );

return <TagName { ...innerBlocksProps } />;
Expand Down
14 changes: 11 additions & 3 deletions packages/block-library/src/template-part/editor.scss
Expand Up @@ -25,9 +25,13 @@

.is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block-template-part,
.is-outline-mode .block-editor-block-list__block:not(.remove-outline).is-reusable {
&.is-highlighted,
&.is-selected {
box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
&.is-highlighted::after,
&.is-selected::after {
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-block-synced-color);
}

&.is-hovered::after {
box-shadow: 0 0 0 $border-width var(--wp-block-synced-color);
}

&.block-editor-block-list__block:not([contenteditable]):focus {
Expand All @@ -40,3 +44,7 @@
}
}
}

.is-outline-mode .block-editor-block-list__block:not(.remove-outline).wp-block-template-part.has-editable-outline::after {
border: none;
}
14 changes: 12 additions & 2 deletions packages/edit-post/src/editor.js
Expand Up @@ -32,11 +32,14 @@ function Editor( {
...props
} ) {
const {
initialPost,
currentPost,
onNavigateToEntityRecord,
onNavigateToPreviousEntityRecord,
} = useNavigateToEntityRecord( initialPostId, initialPostType );
} = useNavigateToEntityRecord(
initialPostId,
initialPostType,
'post-only'
);

const { post, template } = useSelect(
( select ) => {
Expand Down Expand Up @@ -80,6 +83,13 @@ function Editor( {
[ settings, onNavigateToEntityRecord, onNavigateToPreviousEntityRecord ]
);

const initialPost = useMemo( () => {
return {
type: initialPostType,
id: initialPostId,
};
}, [ initialPostType, initialPostId ] );

if ( ! post ) {
return null;
}
Expand Down
61 changes: 37 additions & 24 deletions packages/edit-post/src/hooks/use-navigate-to-entity-record.js
@@ -1,7 +1,9 @@
/**
* WordPress dependencies
*/
import { useCallback, useReducer, useMemo } from '@wordpress/element';
import { useCallback, useReducer } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';

/**
* A hook that records the 'entity' history in the post editor as a user
Expand All @@ -11,20 +13,22 @@ import { useCallback, useReducer, useMemo } from '@wordpress/element';
*
* Used to control displaying UI elements like the back button.
*
* @param {number} initialPostId The post id of the post when the editor loaded.
* @param {string} initialPostType The post type of the post when the editor loaded.
* @param {number} initialPostId The post id of the post when the editor loaded.
* @param {string} initialPostType The post type of the post when the editor loaded.
* @param {string} defaultRenderingMode The rendering mode to switch to when navigating.
*
* @return {Object} An object containing the `currentPost` variable and
* `onNavigateToEntityRecord` and `onNavigateToPreviousEntityRecord` functions.
*/
export default function useNavigateToEntityRecord(
initialPostId,
initialPostType
initialPostType,
defaultRenderingMode
) {
const [ postHistory, dispatch ] = useReducer(
( historyState, { type, post } ) => {
( historyState, { type, post, previousRenderingMode } ) => {
if ( type === 'push' ) {
return [ ...historyState, post ];
return [ ...historyState, { post, previousRenderingMode } ];
}
if ( type === 'pop' ) {
// Try to leave one item in the history.
Expand All @@ -34,32 +38,41 @@ export default function useNavigateToEntityRecord(
}
return historyState;
},
[ { postId: initialPostId, postType: initialPostType } ]
[
{
post: { postId: initialPostId, postType: initialPostType },
},
]
);

const initialPost = useMemo( () => {
return {
type: initialPostType,
id: initialPostId,
};
}, [ initialPostType, initialPostId ] );
andrewserong marked this conversation as resolved.
Show resolved Hide resolved
const { post, previousRenderingMode } =
postHistory[ postHistory.length - 1 ];

const onNavigateToEntityRecord = useCallback( ( params ) => {
dispatch( {
type: 'push',
post: { postId: params.postId, postType: params.postType },
} );
}, [] );
const { getRenderingMode } = useSelect( editorStore );
const { setRenderingMode } = useDispatch( editorStore );

const onNavigateToEntityRecord = useCallback(
( params ) => {
dispatch( {
type: 'push',
post: { postId: params.postId, postType: params.postType },
// Save the current rendering mode so we can restore it when navigating back.
previousRenderingMode: getRenderingMode(),
} );
setRenderingMode( defaultRenderingMode );
},
[ getRenderingMode, setRenderingMode, defaultRenderingMode ]
);

const onNavigateToPreviousEntityRecord = useCallback( () => {
dispatch( { type: 'pop' } );
}, [] );

const currentPost = postHistory[ postHistory.length - 1 ];
if ( previousRenderingMode ) {
setRenderingMode( previousRenderingMode );
}
}, [ setRenderingMode, previousRenderingMode ] );

return {
currentPost,
initialPost,
currentPost: post,
onNavigateToEntityRecord,
onNavigateToPreviousEntityRecord:
postHistory.length > 1
Expand Down
Expand Up @@ -6,7 +6,6 @@ import {
store as blockEditorStore,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
import { useMemo } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -15,15 +14,16 @@ import { unlock } from '../../../lock-unlock';

const { BlockQuickNavigation } = unlock( blockEditorPrivateApis );

const PAGE_CONTENT_BLOCKS = [
'core/post-content',
'core/post-featured-image',
'core/post-title',
];

export default function PageContent() {
const clientIdsTree = useSelect(
( select ) =>
unlock( select( blockEditorStore ) ).getEnabledClientIdsTree(),
[]
);
const clientIds = useMemo(
() => clientIdsTree.map( ( { clientId } ) => clientId ),
[ clientIdsTree ]
);
const clientIds = useSelect( ( select ) => {
const { getBlocksByName } = select( blockEditorStore );
return getBlocksByName( PAGE_CONTENT_BLOCKS );
}, [] );
return <BlockQuickNavigation clientIds={ clientIds } />;
}
1 change: 0 additions & 1 deletion packages/edit-site/src/hooks/index.js
Expand Up @@ -3,4 +3,3 @@
*/
import './components';
import './push-changes-to-global-styles';
import './template-part-edit';