diff --git a/lib/template-loader.php b/lib/template-loader.php index 82a86e7a539e3d..b534db1637b2e4 100644 --- a/lib/template-loader.php +++ b/lib/template-loader.php @@ -255,18 +255,7 @@ function gutenberg_find_template_post_and_parts( $template_type, $template_hiera // See if there is a theme block template with higher priority than the resolved template post. $higher_priority_block_template_path = null; $higher_priority_block_template_priority = PHP_INT_MAX; - $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' ); - $block_template_files = is_array( $block_template_files ) ? $block_template_files : array(); - if ( is_child_theme() ) { - $child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' ); - $child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array(); - $block_template_files = array_merge( $block_template_files, $child_block_template_files ); - } - if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) { - $demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' ); - $demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array(); - $block_template_files = array_merge( $block_template_files, $demo_block_template_files ); - } + $block_template_files = gutenberg_get_template_paths(); foreach ( $block_template_files as $path ) { if ( ! isset( $slug_priorities[ basename( $path, '.html' ) ] ) ) { continue; diff --git a/lib/templates.php b/lib/templates.php index 971398dbd4ff8c..d0c9075b8db848 100644 --- a/lib/templates.php +++ b/lib/templates.php @@ -5,6 +5,31 @@ * @package gutenberg */ +/** + * Returns all block template file path of the current theme and its parent theme. + * Includes demo block template files if demo experiment is enabled. + * + * @return array $block_template_files A list of paths to all template files. + */ +function gutenberg_get_template_paths() { + $block_template_files = glob( get_stylesheet_directory() . '/block-templates/*.html' ); + $block_template_files = is_array( $block_template_files ) ? $block_template_files : array(); + + if ( is_child_theme() ) { + $child_block_template_files = glob( get_template_directory() . '/block-templates/*.html' ); + $child_block_template_files = is_array( $child_block_template_files ) ? $child_block_template_files : array(); + $block_template_files = array_merge( $block_template_files, $child_block_template_files ); + } + + if ( gutenberg_is_experiment_enabled( 'gutenberg-full-site-editing-demo' ) ) { + $demo_block_template_files = glob( dirname( __FILE__ ) . '/demo-block-templates/*.html' ); + $demo_block_template_files = is_array( $demo_block_template_files ) ? $demo_block_template_files : array(); + $block_template_files = array_merge( $block_template_files, $demo_block_template_files ); + } + + return $block_template_files; +} + /** * Registers block editor 'wp_template' post type. */ @@ -177,6 +202,13 @@ function filter_rest_wp_template_collection_params( $query_params ) { * @return array Filtered $args. */ function filter_rest_wp_template_query( $args, $request ) { + // Create auto-drafts for each theme template files. + $block_template_files = gutenberg_get_template_paths(); + foreach ( $block_template_files as $path ) { + $template_type = basename( $path, '.html' ); + gutenberg_find_template_post_and_parts( $template_type, array( $template_type ) ); + } + if ( $request['resolved'] ) { $template_ids = array( 0 ); // Return nothing by default (the 0 is needed for `post__in`). $template_types = $request['slug'] ? $request['slug'] : get_template_types(); diff --git a/packages/e2e-tests/experimental-features.js b/packages/e2e-tests/experimental-features.js index 2a270a8431b066..bc472b4896f4ff 100644 --- a/packages/e2e-tests/experimental-features.js +++ b/packages/e2e-tests/experimental-features.js @@ -38,13 +38,55 @@ export function useExperimentalFeatures( features ) { afterAll( () => setExperimentalFeaturesState( features, false ) ); } -export const openNavigation = async () => { - const isOpen = !! ( await page.$( - '.edit-site-navigation-toggle.is-open' - ) ); - - if ( ! isOpen ) { - await page.click( '.edit-site-navigation-toggle__button' ); - await page.waitForSelector( '.edit-site-navigation-panel' ); - } +export const navigationPanel = { + async open() { + const isOpen = !! ( await page.$( + '.edit-site-navigation-toggle.is-open' + ) ); + + if ( ! isOpen ) { + await page.click( '.edit-site-navigation-toggle__button' ); + await page.waitForSelector( '.edit-site-navigation-panel' ); + } + }, + + async isRoot() { + const isBackToDashboardButtonVisible = !! ( await page.$( + '.edit-site-navigation-panel .edit-site-navigation-panel__back-to-dashboard' + ) ); + + return isBackToDashboardButtonVisible; + }, + + async back() { + await page.click( '.components-navigation__back-button' ); + }, + + async navigate( menus ) { + if ( ! Array.isArray( menus ) ) { + menus = [ menus ]; + } + + for ( const menu of menus ) { + ( await this.getItemByText( menu ) ).click(); + } + }, + + async backToRoot() { + while ( ! ( await this.isRoot() ) ) { + await this.back(); + } + }, + + async getItemByText( text ) { + const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ text }")]`; + await page.waitForXPath( selector ); + const [ item ] = await page.$x( selector ); + return item; + }, + + async clickItemByText( text ) { + const item = await this.getItemByText( text ); + await item.click(); + }, }; diff --git a/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js b/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js index 6804e87d8759a0..144401156a64fe 100644 --- a/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js +++ b/packages/e2e-tests/specs/experiments/multi-entity-editing.test.js @@ -20,7 +20,7 @@ import { addQueryArgs } from '@wordpress/url'; */ import { useExperimentalFeatures, - openNavigation, + navigationPanel, } from '../../experimental-features'; const visitSiteEditor = async () => { @@ -34,12 +34,11 @@ const visitSiteEditor = async () => { ); }; -const getTemplateDropdownElement = async ( itemName ) => { - await openNavigation(); - const selector = `//div[contains(@class, "edit-site-navigation-panel")]//button[contains(., "${ itemName }")]`; - await page.waitForXPath( selector ); - const [ item ] = await page.$x( selector ); - return item; +const clickTemplateItem = async ( menus, itemName ) => { + await navigationPanel.open(); + await navigationPanel.backToRoot(); + await navigationPanel.navigate( menus ); + await navigationPanel.clickItemByText( itemName ); }; const createTemplatePart = async ( @@ -169,8 +168,7 @@ describe( 'Multi-entity editor states', () => { } ); it( 'should not dirty an entity by switching to it in the template dropdown', async () => { - const templatePartButton = await getTemplateDropdownElement( 'header' ); - await templatePartButton.click(); + await clickTemplateItem( 'Template parts', 'header' ); // Wait for blocks to load. await page.waitForSelector( '.wp-block' ); @@ -178,8 +176,7 @@ describe( 'Multi-entity editor states', () => { expect( await isEntityDirty( 'front-page' ) ).toBe( false ); // Switch back and make sure it is still clean. - const templateButton = await getTemplateDropdownElement( 'front-page' ); - await templateButton.click(); + await clickTemplateItem( 'Templates', 'Front page' ); await page.waitForSelector( '.wp-block' ); expect( await isEntityDirty( 'header' ) ).toBe( false ); expect( await isEntityDirty( 'front-page' ) ).toBe( false ); diff --git a/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js index af8cb346e19f83..a2b9b5ee0237ff 100644 --- a/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js +++ b/packages/e2e-tests/specs/experiments/multi-entity-saving.test.js @@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url'; */ import { useExperimentalFeatures, - openNavigation, + navigationPanel, } from '../../experimental-features'; describe( 'Multi-entity save flow', () => { @@ -221,7 +221,6 @@ describe( 'Multi-entity save flow', () => { describe( 'Site Editor', () => { // Selectors - Site editor specific. - const demoTemplateSelector = '//button[contains(., "front-page")]'; const saveSiteSelector = '.edit-site-save-button__button'; const activeSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=false]`; const disabledSaveSiteSelector = `${ saveSiteSelector }[aria-disabled=true]`; @@ -235,11 +234,10 @@ describe( 'Multi-entity save flow', () => { await visitAdminPage( 'admin.php', query ); // Ensure we are on 'front-page' demo template. - await openNavigation(); - const demoTemplateButton = await page.waitForXPath( - demoTemplateSelector - ); - await demoTemplateButton.click(); + await navigationPanel.open(); + await navigationPanel.backToRoot(); + await navigationPanel.navigate( 'Templates' ); + await navigationPanel.clickItemByText( 'Front page' ); // Insert a new template part placeholder. await insertBlock( 'Template Part' ); diff --git a/packages/e2e-tests/specs/experiments/template-part.test.js b/packages/e2e-tests/specs/experiments/template-part.test.js index dfec46717a562d..c89c15766d24c0 100644 --- a/packages/e2e-tests/specs/experiments/template-part.test.js +++ b/packages/e2e-tests/specs/experiments/template-part.test.js @@ -15,7 +15,7 @@ import { addQueryArgs } from '@wordpress/url'; */ import { useExperimentalFeatures, - openNavigation, + navigationPanel, } from '../../experimental-features'; describe( 'Template Part', () => { @@ -46,11 +46,10 @@ describe( 'Template Part', () => { it( 'Should load customizations when in a template even if only the slug and theme attributes are set.', async () => { // Switch to editing the header template part. - await openNavigation(); - const switchToHeaderTemplatePartButton = await page.waitForXPath( - '//button[contains(text(), "header")]' - ); - await switchToHeaderTemplatePartButton.click(); + await navigationPanel.open(); + await navigationPanel.backToRoot(); + await navigationPanel.navigate( 'Template parts' ); + await navigationPanel.clickItemByText( 'header' ); // Edit it. await insertBlock( 'Paragraph' ); @@ -64,11 +63,10 @@ describe( 'Template Part', () => { ); // Switch back to the front page template. - await openNavigation(); - const [ switchToFrontPageTemplateButton ] = await page.$x( - '//button[contains(text(), "front-page")]' - ); - await switchToFrontPageTemplateButton.click(); + await navigationPanel.open(); + await navigationPanel.backToRoot(); + await navigationPanel.navigate( 'Templates' ); + await navigationPanel.clickItemByText( 'Front page' ); // Verify that the header template part is updated. const [ headerTemplatePart ] = await page.$x( diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js new file mode 100644 index 00000000000000..2b849edfc2a9e7 --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/constants.js @@ -0,0 +1,64 @@ +export const TEMPLATES_DEFAULT_DETAILS = { + // General + 'front-page': { + title: 'Front page', + description: '', + }, + archive: { + title: 'Archive', + description: + 'Displays the content lists when no other template is found', + }, + single: { + title: 'Single', + description: 'Displays the content of a single post', + }, + singular: { + title: 'Singular', + description: 'Displays the content of a single page', + }, + index: { + title: 'Default (index)', + description: 'Displays the content of a single page', + }, + search: { + title: 'Search results', + description: '', + }, + '404': { + title: '404', + description: 'Displayed when a non-existing page requested', + }, + + // Pages + page: { + title: 'Default (Page)', + description: 'Displays the content of a single page', + }, + + // Posts + home: { + title: 'Posts (home)', + description: 'Displayed on your homepage', + }, + 'archive-post': { + title: 'Default (Post archive)', + description: 'Displays a list of posts', + }, + 'single-post': { + title: 'Default (Single post)', + description: 'Displays the content of a single post', + }, +}; + +export const TEMPLATES_GENERAL = [ + 'front-page', + 'archive', + 'single', + 'singular', + 'index', + 'search', + '404', +]; + +export const TEMPLATES_POSTS = [ 'single-post', 'archive-post', 'home' ]; diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js index 36464bcab8d9ec..05fb956e66a497 100644 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/index.js @@ -1,11 +1,13 @@ /** * WordPress dependencies */ -import { useEffect, useRef } from '@wordpress/element'; +import { useEffect, useRef, useState } from '@wordpress/element'; import { __experimentalNavigation as Navigation, __experimentalNavigationMenu as NavigationMenu, + __experimentalNavigationItem as NavigationItem, __experimentalNavigationBackButton as NavigationBackButton, + createSlotFill, } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; @@ -13,68 +15,78 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import TemplateSwitcher from './template-switcher'; +import TemplatesMenu from './menus/templates'; +import TemplatePartsMenu from './menus/template-parts'; + +export const { + Fill: NavigationPanelPreviewFill, + Slot: NavigationPanelPreviewSlot, +} = createSlotFill( 'EditSiteNavigationPanelPreview' ); const NavigationPanel = () => { + const [ activeMenu, setActiveMenu ] = useState( 'root' ); const ref = useRef(); useEffect( () => { ref.current.focus(); }, [ ref ] ); - const { templateId, templatePartId, templateType, page } = useSelect( + const { templateId, templatePartId, templateType } = useSelect( ( select ) => { const { getTemplateId, getTemplatePartId, getTemplateType, - getPage, } = select( 'core/edit-site' ); return { templateId: getTemplateId(), templatePartId: getTemplatePartId(), templateType: getTemplateType(), - page: getPage(), }; }, [] ); - const { - setTemplate, - addTemplate, - removeTemplate, - setTemplatePart, - } = useDispatch( 'core/edit-site' ); + const { setTemplate, setTemplatePart } = useDispatch( 'core/edit-site' ); return (
- + { activeMenu === 'root' && ( + + ) } + + + - - + + + + + +
); }; diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js new file mode 100644 index 00000000000000..d1005478f45270 --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/template-parts.js @@ -0,0 +1,46 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useSelect } from '@wordpress/data'; +import { + __experimentalNavigationItem as NavigationItem, + __experimentalNavigationMenu as NavigationMenu, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TemplateNavigationItems from '../template-navigation-items'; + +export default function TemplatePartsMenu( { onActivateItem } ) { + const templateParts = useSelect( ( select ) => { + const currentTheme = select( 'core' ).getCurrentTheme()?.textdomain; + + return select( 'core' ).getEntityRecords( + 'postType', + 'wp_template_part', + { + theme: currentTheme, + status: [ 'publish', 'auto-draft' ], + per_page: -1, + } + ); + }, [] ); + + return ( + + + + { ! templateParts && } + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js new file mode 100644 index 00000000000000..7316015029bc21 --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-all.js @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { __experimentalNavigationMenu as NavigationMenu } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TemplateNavigationItems from '../template-navigation-items'; + +export default function TemplatesAllMenu( { templates, onActivateItem } ) { + return ( + + + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js new file mode 100644 index 00000000000000..6cd226c251c04f --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-pages.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { + __experimentalNavigationGroup as NavigationGroup, + __experimentalNavigationMenu as NavigationMenu, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TemplateNavigationItems from '../template-navigation-items'; + +export default function TemplatesPagesMenu( { templates, onActivateItem } ) { + const defaultTemplate = templates?.find( ( { slug } ) => slug === 'page' ); + const specificPageTemplates = templates?.filter( ( { slug } ) => + slug.startsWith( 'page-' ) + ); + + return ( + + + + + + { defaultTemplate && ( + + + + ) } + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js new file mode 100644 index 00000000000000..5716abda6bdc8e --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates-posts.js @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { + __experimentalNavigationGroup as NavigationGroup, + __experimentalNavigationMenu as NavigationMenu, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TemplateNavigationItems from '../template-navigation-items'; +import { TEMPLATES_POSTS } from '../constants'; + +export default function TemplatePostsMenu( { templates, onActivateItem } ) { + const generalTemplates = templates?.find( ( { slug } ) => + TEMPLATES_POSTS.includes( slug ) + ); + const specificTemplates = templates?.filter( ( { slug } ) => + slug.startsWith( 'post-' ) + ); + + return ( + + + + + + + + + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js new file mode 100644 index 00000000000000..471b9a4a1d2c84 --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/menus/templates.js @@ -0,0 +1,60 @@ +/** + * WordPress dependencies + */ +import { + __experimentalNavigationItem as NavigationItem, + __experimentalNavigationMenu as NavigationMenu, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import TemplatesPagesMenu from './templates-pages'; +import TemplateNavigationItems from '../template-navigation-items'; +import TemplatePostsMenu from './templates-posts'; +import { TEMPLATES_GENERAL } from '../constants'; +import { useSelect } from '@wordpress/data'; +import TemplatesAllMenu from './templates-all'; + +export default function TemplatesMenu( { onActivateItem } ) { + const templates = useSelect( + ( select ) => + select( 'core' ).getEntityRecords( 'postType', 'wp_template', { + status: [ 'publish', 'auto-draft' ], + per_page: -1, + } ), + [] + ); + + const generalTemplates = templates?.filter( ( { slug } ) => + TEMPLATES_GENERAL.includes( slug ) + ); + + return ( + + + + + + + + + + + + + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss b/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss index 452e967387e996..ab0210884ae17c 100644 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/style.scss @@ -17,29 +17,6 @@ .components-navigation { height: 100%; } - - .components-navigation__item { - position: relative; - - .edit-site-template-switcher__label-home-icon svg path { - color: inherit; - } - - &.is-active { - .edit-site-template-switcher__label-customized-dot { - background: #fff; - } - } - } - - .edit-site-template-switcher__label-home-icon { - top: 50%; - transform: translateY(-50%); - } - - .edit-site-template-switcher__label-customized-dot { - right: 8px; - } } .edit-site-navigation-panel__back-to-dashboard.components-button.is-tertiary { @@ -73,3 +50,26 @@ display: block; } } + +.edit-site-navigation-panel__template-item { + display: block; + + &.is-active .edit-site-navigation-panel__template-item-description { + color: $gray-100; + } + + button { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + height: auto; + min-height: $button-size; + text-align: left; + } +} + +.edit-site-navigation-panel__template-item-description { + padding-top: $grid-unit-05; + color: $gray-700; +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js new file mode 100644 index 00000000000000..a0456057d15bce --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-navigation-items.js @@ -0,0 +1,86 @@ +/** + * WordPress dependencies + */ +import { + Button, + __experimentalNavigationItem as NavigationItem, +} from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import TemplatePreview from './template-preview'; +import { NavigationPanelPreviewFill } from '.'; +import { TEMPLATES_DEFAULT_DETAILS } from './constants'; + +export default function TemplateNavigationItems( { + entityType = 'wp_template', + templates, + onActivateItem, +} ) { + const [ hoveredTemplate, setHoveredTemplate ] = useState(); + + const onMouseEnterTemplate = ( template ) => setHoveredTemplate( template ); + const onMouseLeaveTemplate = () => setHoveredTemplate( null ); + + if ( ! templates ) { + return null; + } + + if ( ! Array.isArray( templates ) ) { + templates = [ templates ]; + } + + return ( + <> + { templates.map( ( template ) => { + const { title: defaultTitle, description: defaultDescription } = + TEMPLATES_DEFAULT_DETAILS[ template.slug ] ?? {}; + const key = `${ entityType }-${ template.id }`; + + let title = template?.title?.rendered ?? template.slug; + if ( title !== template.slug ) { + title = template.title.rendered; + } else if ( defaultTitle ) { + title = defaultTitle; + } + + const description = + template?.excerpt?.rendered || defaultDescription; + + return ( + + + + ); + } ) } + + { hoveredTemplate?.content?.raw && ( + + + + ) } + + ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js new file mode 100644 index 00000000000000..e27eeb7a514128 --- /dev/null +++ b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-preview.js @@ -0,0 +1,22 @@ +/** + * WordPress dependencies + */ +import { parse } from '@wordpress/blocks'; +import { BlockPreview } from '@wordpress/block-editor'; +import { useMemo } from '@wordpress/element'; + +export default function TemplatePreview( { rawContent } ) { + const blocks = useMemo( () => ( rawContent ? parse( rawContent ) : [] ), [ + rawContent, + ] ); + + if ( ! blocks || blocks.length === 0 ) { + return null; + } + + return ( +
+ +
+ ); +} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js deleted file mode 100644 index 570ce7640e4383..00000000000000 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/index.js +++ /dev/null @@ -1,206 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { useSelect } from '@wordpress/data'; -import { useState } from '@wordpress/element'; -import { - Button, - Tooltip, - __experimentalNavigationGroup as NavigationGroup, - __experimentalNavigationItem as NavigationItem, -} from '@wordpress/components'; -import { Icon, home, plus, undo } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import TemplatePreview from './template-preview'; -import ThemePreview from './theme-preview'; - -const TEMPLATE_OVERRIDES = { - page: ( slug ) => `page-${ slug }`, - category: ( slug ) => `category-${ slug }`, - post: ( slug ) => `single-post-${ slug }`, -}; - -function TemplateNavigationItemWithIcon( { - item, - icon, - iconLabel, - homeId, - template, - title, - ...props -} ) { - if ( ! icon && ! iconLabel && template ) { - if ( template.id === homeId ) { - icon = home; - iconLabel = __( 'Home' ); - } else if ( template.status !== 'auto-draft' ) { - icon = ( - - ); - iconLabel = __( 'Customized' ); - } - } - - return ( - - - - ); -} - -export default function TemplateSwitcher( { - page, - activeId, - onActiveIdChange, - onActiveTemplatePartIdChange, - onAddTemplate, - onRemoveTemplate, -} ) { - const [ hoveredTemplatePartId, setHoveredTemplatePartId ] = useState(); - const [ themePreviewVisible, setThemePreviewVisible ] = useState( false ); - - const onMouseEnterTemplatePart = ( id ) => setHoveredTemplatePartId( id ); - const onMouseLeaveTemplatePart = () => setHoveredTemplatePartId( null ); - - const onMouseEnterTheme = () => setThemePreviewVisible( true ); - const onMouseLeaveTheme = () => setThemePreviewVisible( false ); - - const { currentTheme, template, templateParts, homeId } = useSelect( - ( select ) => { - const { - getCurrentTheme, - getEntityRecord, - getEntityRecords, - } = select( 'core' ); - - const _template = getEntityRecord( - 'postType', - 'wp_template', - activeId - ); - - const { getHomeTemplateId } = select( 'core/edit-site' ); - - return { - currentTheme: getCurrentTheme(), - template: _template, - templateParts: _template - ? getEntityRecords( 'postType', 'wp_template_part', { - resolved: true, - template: _template.slug, - } ) - : null, - homeId: getHomeTemplateId(), - }; - }, - [ activeId ] - ); - - const overwriteSlug = - page && - TEMPLATE_OVERRIDES[ page.type ] && - page.slug && - TEMPLATE_OVERRIDES[ page.type ]( page.slug ); - - const overwriteTemplate = () => - onAddTemplate( { - slug: overwriteSlug, - title: overwriteSlug, - status: 'publish', - content: template.content.raw, - } ); - const revertToParent = () => { - onRemoveTemplate( activeId ); - }; - - return ( - <> - - onActiveIdChange( activeId ) } - /> - - { overwriteSlug && - template && - overwriteSlug !== template.slug && ( - - ) } - - { template && overwriteSlug === template.slug && ( - - ) } - - - - { templateParts?.map( ( templatePart ) => { - const key = `template-part-${ templatePart.id }`; - - return ( - - onActiveTemplatePartIdChange( templatePart.id ) - } - onMouseEnter={ () => - onMouseEnterTemplatePart( templatePart.id ) - } - onMouseLeave={ onMouseLeaveTemplatePart } - /> - ); - } ) } - - { ( ! templateParts || templateParts.length === 0 ) && ( - - ) } - - - - - - - { hoveredTemplatePartId && ( - - ) } - - { currentTheme && themePreviewVisible && ( - - ) } - - ); -} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss deleted file mode 100644 index 2e0a1fb6d1a43a..00000000000000 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/style.scss +++ /dev/null @@ -1,45 +0,0 @@ -.edit-site-template-switcher__navigation-item { - position: relative; - - &.is-active { - .edit-site-template-switcher__customized-dot { - background: #fff; - } - } - - .edit-site-template-switcher__navigation-item-icon svg path { - color: inherit; - } -} - -.edit-site-template-switcher__navigation-item-icon { - width: 24px; - height: 24px; - position: absolute; - right: 20px; - top: 50%; - transform: translateY(-50%); -} - -.edit-site-template-switcher__customized-dot { - position: absolute; - right: 8px; - top: 50%; - margin-top: -4px; - width: 8px; - height: 8px; - display: block; - background: var(--wp-admin-theme-color); - border-radius: 50%; -} - -.edit-site-template-switcher__theme-preview-name { - font-weight: 500; - font-size: $big-font-size; -} - -.edit-site-template-switcher__theme-preview-screenshot { - margin-bottom: $grid-unit-15; - margin-top: $grid-unit-15; - max-width: 100%; -} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js deleted file mode 100644 index 56193a6bef08e0..00000000000000 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/template-preview.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * WordPress dependencies - */ -import { parse } from '@wordpress/blocks'; -import { useSelect } from '@wordpress/data'; -import { BlockPreview } from '@wordpress/block-editor'; -import { useMemo } from '@wordpress/element'; - -export default function TemplatePreview( { entityId } ) { - const template = useSelect( - ( select ) => - select( 'core' ).getEntityRecord( - 'postType', - 'wp_template_part', - entityId - ), - [ entityId ] - ); - - const templateRawContent = template?.content?.raw || ''; - const blocks = useMemo( - () => ( template ? parse( templateRawContent ) : [] ), - [ templateRawContent ] - ); - - if ( ! blocks || blocks.length === 0 ) { - return null; - } - - return ( -
- -
- ); -} diff --git a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js b/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js deleted file mode 100644 index 23d6c2889dc09c..00000000000000 --- a/packages/edit-site/src/components/left-sidebar/navigation-panel/template-switcher/theme-preview.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * External dependencies - */ -import { truncate } from 'lodash'; - -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; - -export default function ThemePreview( { - theme: { author, description, name, screenshot, version }, -} ) { - return ( -
- { ' ' } - - { 'v' + version } - -
- { - // translators: %s: theme author name. - sprintf( __( 'By %s' ), [ author.raw ] ) - } -
- { -
- { truncate( - // We can't use `description.rendered` here because we are truncating the string - // `description.rendered` might contain HTML tags which doesn't play nicely with truncating - // truncate function might truncate in the middle of an HTML tag so we never - // close the HTML tag we are already in - description.raw, - { - length: 120, - separator: /\. +/, - } - ) } -
-
- ); -} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index 86c502bbe7360c..2d00d96f215554 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -8,7 +8,6 @@ @import "./components/header/navigation-toggle/style.scss"; @import "./components/left-sidebar/inserter-panel/style.scss"; @import "./components/left-sidebar/navigation-panel/style.scss"; -@import "./components/left-sidebar/navigation-panel/template-switcher/style.scss"; @import "./components/notices/style.scss"; @import "./components/page-switcher/style.scss"; @import "./components/sidebar/style.scss";