Skip to content

Commit

Permalink
Allow selecting template parts in page content focus mode (WordPress#…
Browse files Browse the repository at this point in the history
…60010)

* Allow selecting template parts in page content focus mode

* Show block name/icon in toolbar when editing mode is contentOnly

* Only show page content blocks in PageContent sidebar section

* Fix pages.spec.js

* Improve clarify of if()

* Move template part Edit button from @wordpress/edit-site to @wordpress/editor

* Rendering mode should be 'all' in post editor when editing a template or template part

* Revert "Rendering mode should be 'all' in post editor when editing a template or template part"

This reverts commit 348889e.

* Reset and remember rendering mode when navigating in post editor

* Remove unsupported rendering mode from docs

* Add 'Edit' button to Template Part block natively

* Disable appending into a template part

* Always show purple outline on template parts

Co-authored-by: noisysocks <noisysocks@git.wordpress.org>
Co-authored-by: SaxonF <saxonafletcher@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
Co-authored-by: richtabor <richtabor@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: jasmussen <joen@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: bacoords <bacoords@git.wordpress.org>
  • Loading branch information
10 people authored and carstingaxion committed Mar 27, 2024
1 parent a401a8c commit db6c9d0
Show file tree
Hide file tree
Showing 15 changed files with 229 additions and 213 deletions.
1 change: 0 additions & 1 deletion docs/reference-guides/data/data-core-editor.md
Original file line number Diff line number Diff line change
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
4 changes: 2 additions & 2 deletions packages/block-editor/src/components/block-switcher/index.js
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -170,26 +170,29 @@ export function PrivateBlockToolbar( {
{ isUsingBindings && canBindBlock( blockName ) && (
<BlockBindingsIndicator />
) }
{ ( shouldShowVisualToolbar || isMultiToolbar ) &&
isDefaultEditingMode && (
<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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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 ] );
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
*/
import './components';
import './push-changes-to-global-styles';
import './template-part-edit';
Loading

0 comments on commit db6c9d0

Please sign in to comment.