diff --git a/backport-changelog/6.8/7903.md b/backport-changelog/6.8/7903.md
new file mode 100644
index 00000000000000..cb20d8d2dd2b1b
--- /dev/null
+++ b/backport-changelog/6.8/7903.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/7903
+
+* https://github.com/WordPress/gutenberg/pull/67199
diff --git a/lib/compat/wordpress-6.8/site-editor.php b/lib/compat/wordpress-6.8/site-editor.php
new file mode 100644
index 00000000000000..cde108830b1d2c
--- /dev/null
+++ b/lib/compat/wordpress-6.8/site-editor.php
@@ -0,0 +1,124 @@
+ '/wp_navigation/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_navigation' === $_REQUEST['postType'] && empty( $_REQUEST['postId'] ) ) {
+ return add_query_arg( array( 'p' => '/navigation' ), remove_query_arg( 'postType' ) );
+ }
+
+ if ( isset( $_REQUEST['path'] ) && '/wp_global_styles' === $_REQUEST['path'] ) {
+ return add_query_arg( array( 'p' => '/styles' ), remove_query_arg( 'path' ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'page' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) {
+ return add_query_arg( array( 'p' => '/page' ), remove_query_arg( 'postType' ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'page' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) {
+ return add_query_arg( array( 'p' => '/page/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_template' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) {
+ return add_query_arg( array( 'p' => '/template' ), remove_query_arg( 'postType' ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_template' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) {
+ return add_query_arg( array( 'p' => '/wp_template/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_block' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) {
+ return add_query_arg( array( 'p' => '/pattern' ), remove_query_arg( 'postType' ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_block' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) {
+ return add_query_arg( array( 'p' => '/wp_block/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_template_part' === $_REQUEST['postType'] && ( empty( $_REQUEST['canvas'] ) || empty( $_REQUEST['postId'] ) ) ) {
+ return add_query_arg( array( 'p' => '/pattern' ) );
+ }
+
+ if ( isset( $_REQUEST['postType'] ) && 'wp_template_part' === $_REQUEST['postType'] && ! empty( $_REQUEST['postId'] ) ) {
+ return add_query_arg( array( 'p' => '/wp_template_part/' . $_REQUEST['postId'] ), remove_query_arg( array( 'postType', 'postId' ) ) );
+ }
+
+ // The following redirects are for backward compatibility with the old site editor URLs.
+ if ( isset( $_REQUEST['path'] ) && '/wp_template_part/all' === $_REQUEST['path'] ) {
+ return add_query_arg(
+ array(
+ 'p' => '/pattern',
+ 'postType' => 'wp_template_part',
+ ),
+ remove_query_arg( 'path' )
+ );
+ }
+
+ if ( isset( $_REQUEST['path'] ) && '/page' === $_REQUEST['path'] ) {
+ return add_query_arg( array( 'p' => '/page' ), remove_query_arg( 'path' ) );
+ }
+
+ if ( isset( $_REQUEST['path'] ) && '/wp_template' === $_REQUEST['path'] ) {
+ return add_query_arg( array( 'p' => '/template' ), remove_query_arg( 'path' ) );
+ }
+
+ if ( isset( $_REQUEST['path'] ) && '/patterns' === $_REQUEST['path'] ) {
+ return add_query_arg( array( 'p' => '/pattern' ), remove_query_arg( 'path' ) );
+ }
+
+ if ( isset( $_REQUEST['path'] ) && '/navigation' === $_REQUEST['path'] ) {
+ return add_query_arg( array( 'p' => '/navigation' ), remove_query_arg( 'path' ) );
+ }
+
+ return add_query_arg( array( 'p' => '/' ) );
+}
+
+function gutenberg_redirect_site_editor_deprecated_urls() {
+ $redirection = gutenberg_get_site_editor_redirection();
+ if ( false !== $redirection ) {
+ wp_redirect( $redirection, 301 );
+ exit;
+ }
+}
+add_action( 'admin_init', 'gutenberg_redirect_site_editor_deprecated_urls' );
+
+/**
+ * Filter the `wp_die_handler` to allow access to the Site Editor's new pages page
+ * for Classic themes.
+ *
+ * site-editor.php's access is forbidden for hybrid/classic themes and only allowed with some very special query args (some very special pages like template parts...).
+ * The only way to disable this protection since we're changing the urls in Gutenberg is to override the wp_die_handler.
+ *
+ * @param callable $default_handler The default handler.
+ * @return callable The default handler or a custom handler.
+ */
+function gutenberg_styles_wp_die_handler( $default_handler ) {
+ if ( ! wp_is_block_theme() && str_contains( $_SERVER['REQUEST_URI'], 'site-editor.php' ) && isset( $_GET['p'] ) ) {
+ return '__return_false';
+ }
+ return $default_handler;
+}
+add_filter( 'wp_die_handler', 'gutenberg_styles_wp_die_handler' );
diff --git a/lib/experimental/posts/load.php b/lib/experimental/posts/load.php
index 7321392b11a25d..699534f1886f52 100644
--- a/lib/experimental/posts/load.php
+++ b/lib/experimental/posts/load.php
@@ -69,18 +69,6 @@ function gutenberg_posts_dashboard() {
echo '
';
}
-/**
- * Redirects to the new posts dashboard page and adds the postType query arg.
- */
-function gutenberg_add_post_type_arg() {
- global $pagenow;
- if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) && 'gutenberg-posts-dashboard' === $_GET['page'] && empty( $_GET['postType'] ) ) {
- wp_redirect( admin_url( '/admin.php?page=gutenberg-posts-dashboard&postType=post' ) );
- exit;
- }
-}
-add_action( 'admin_init', 'gutenberg_add_post_type_arg' );
-
/**
* Replaces the default posts menu item with the new posts dashboard.
*/
diff --git a/lib/load.php b/lib/load.php
index 85d1c7e3292b50..97c5404a3a3ead 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -98,6 +98,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.8/blocks.php';
require __DIR__ . '/compat/wordpress-6.8/functions.php';
require __DIR__ . '/compat/wordpress-6.8/post.php';
+require __DIR__ . '/compat/wordpress-6.8/site-editor.php';
// Experimental features.
require __DIR__ . '/experimental/block-editor-settings-mobile.php';
diff --git a/package-lock.json b/package-lock.json
index ccf779f2d67eab..dc0c18f3b6ac5e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -44492,6 +44492,12 @@
"node": ">=10.0.0"
}
},
+ "node_modules/route-recognizer": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz",
+ "integrity": "sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==",
+ "license": "MIT"
+ },
"node_modules/rrweb-cssom": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
@@ -55563,10 +55569,12 @@
"license": "GPL-2.0-or-later",
"dependencies": {
"@babel/runtime": "7.25.7",
+ "@wordpress/compose": "*",
"@wordpress/element": "*",
"@wordpress/private-apis": "*",
"@wordpress/url": "*",
- "history": "^5.3.0"
+ "history": "^5.3.0",
+ "route-recognizer": "^0.3.4"
},
"engines": {
"node": ">=18.12.0",
diff --git a/packages/core-commands/src/admin-navigation-commands.js b/packages/core-commands/src/admin-navigation-commands.js
index 8a8167bb29b820..f82faa05baae4c 100644
--- a/packages/core-commands/src/admin-navigation-commands.js
+++ b/packages/core-commands/src/admin-navigation-commands.js
@@ -44,11 +44,7 @@ const getAddNewPageCommand = () =>
}
);
if ( page?.id ) {
- history.push( {
- postId: page.id,
- postType: 'page',
- canvas: 'edit',
- } );
+ history.navigate( `/page/${ page.id }?canvas=edit` );
}
} catch ( error ) {
const errorMessage =
diff --git a/packages/core-commands/src/site-editor-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js
index 2785d809d41e03..c1b12a84d4d61a 100644
--- a/packages/core-commands/src/site-editor-navigation-commands.js
+++ b/packages/core-commands/src/site-editor-navigation-commands.js
@@ -136,19 +136,18 @@ const getNavigationCommandLoaderPerPostType = ( postType ) =>
return {
...command,
callback: ( { close } ) => {
- const args = {
- postType,
- postId: record.id,
- canvas: 'edit',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate(
+ `/${ postType }/${ record.id }?canvas=edit`
+ );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: `/${ postType }/${ record.id }`,
+ canvas: 'edit',
+ }
+ );
}
close();
},
@@ -220,19 +219,18 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) =>
: __( '(no title)' ),
icon: icons[ templateType ],
callback: ( { close } ) => {
- const args = {
- postType: templateType,
- postId: record.id,
- canvas: 'edit',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate(
+ `/${ templateType }/${ record.id }?canvas=edit`
+ );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: `/${ templateType }/${ record.id }`,
+ canvas: 'edit',
+ }
+ );
}
close();
},
@@ -249,18 +247,19 @@ const getNavigationCommandLoaderPerTemplate = ( templateType ) =>
label: __( 'Template parts' ),
icon: symbolFilled,
callback: ( { close } ) => {
- const args = {
- postType: 'wp_template_part',
- categoryId: 'all-parts',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate(
+ '/pattern?postType=wp_template_part&categoryId=all-parts'
+ );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/pattern',
+ postType: 'wp_template_part',
+ categoryId: 'all-parts',
+ }
+ );
}
close();
},
@@ -303,17 +302,15 @@ const getSiteEditorBasicNavigationCommands = () =>
label: __( 'Navigation' ),
icon: navigation,
callback: ( { close } ) => {
- const args = {
- postType: 'wp_navigation',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate( '/navigation' );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/navigation',
+ }
+ );
}
close();
},
@@ -324,17 +321,15 @@ const getSiteEditorBasicNavigationCommands = () =>
label: __( 'Styles' ),
icon: styles,
callback: ( { close } ) => {
- const args = {
- path: '/wp_global_styles',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate( '/styles' );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/styles',
+ }
+ );
}
close();
},
@@ -345,17 +340,15 @@ const getSiteEditorBasicNavigationCommands = () =>
label: __( 'Pages' ),
icon: page,
callback: ( { close } ) => {
- const args = {
- postType: 'page',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate( '/page' );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/page',
+ }
+ );
}
close();
},
@@ -366,17 +359,15 @@ const getSiteEditorBasicNavigationCommands = () =>
label: __( 'Templates' ),
icon: layout,
callback: ( { close } ) => {
- const args = {
- postType: 'wp_template',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate( '/template' );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/template',
+ }
+ );
}
close();
},
@@ -389,17 +380,15 @@ const getSiteEditorBasicNavigationCommands = () =>
icon: symbol,
callback: ( { close } ) => {
if ( canCreateTemplate ) {
- const args = {
- postType: 'wp_block',
- };
- const targetUrl = addQueryArgs(
- 'site-editor.php',
- args
- );
if ( isSiteEditor ) {
- history.push( args );
+ history.navigate( '/pattern' );
} else {
- document.location = targetUrl;
+ document.location = addQueryArgs(
+ 'site-editor.php',
+ {
+ p: '/pattern',
+ }
+ );
}
close();
} else {
diff --git a/packages/edit-site/src/components/add-new-pattern/index.js b/packages/edit-site/src/components/add-new-pattern/index.js
index bb9e53da6a5660..63452691c1c373 100644
--- a/packages/edit-site/src/components/add-new-pattern/index.js
+++ b/packages/edit-site/src/components/add-new-pattern/index.js
@@ -69,23 +69,16 @@ export default function AddNewPattern() {
function handleCreatePattern( { pattern } ) {
setShowPatternModal( false );
-
- history.push( {
- postId: pattern.id,
- postType: PATTERN_TYPES.user,
- canvas: 'edit',
- } );
+ history.navigate(
+ `/${ PATTERN_TYPES.user }/${ pattern.id }?canvas=edit`
+ );
}
function handleCreateTemplatePart( templatePart ) {
setShowTemplatePartModal( false );
-
- // Navigate to the created template part editor.
- history.push( {
- postId: templatePart.id,
- postType: TEMPLATE_PART_POST_TYPE,
- canvas: 'edit',
- } );
+ history.navigate(
+ `/${ TEMPLATE_PART_POST_TYPE }/${ templatePart.id }?canvas=edit`
+ );
}
function handleError() {
@@ -203,10 +196,9 @@ export default function AddNewPattern() {
! currentCategoryId &&
categoryId !== 'my-patterns'
) {
- history.push( {
- postType: PATTERN_TYPES.user,
- categoryId: PATTERN_DEFAULT_CATEGORY,
- } );
+ history.navigate(
+ `/pattern?categoryId=${ PATTERN_DEFAULT_CATEGORY }`
+ );
}
createSuccessNotice(
diff --git a/packages/edit-site/src/components/add-new-template/index.js b/packages/edit-site/src/components/add-new-template/index.js
index 1a2d9ea727fa85..5f06ecae6824ae 100644
--- a/packages/edit-site/src/components/add-new-template/index.js
+++ b/packages/edit-site/src/components/add-new-template/index.js
@@ -203,11 +203,9 @@ function NewTemplateModal( { onClose } ) {
);
// Navigate to the created template editor.
- history.push( {
- postId: newTemplate.id,
- postType: TEMPLATE_POST_TYPE,
- canvas: 'edit',
- } );
+ history.navigate(
+ `/${ TEMPLATE_POST_TYPE }/${ newTemplate.id }?canvas=edit`
+ );
createSuccessNotice(
sprintf(
diff --git a/packages/edit-site/src/components/app/index.js b/packages/edit-site/src/components/app/index.js
index 7e4c50d7d00f09..cf13e7baf1b738 100644
--- a/packages/edit-site/src/components/app/index.js
+++ b/packages/edit-site/src/components/app/index.js
@@ -2,35 +2,41 @@
* WordPress dependencies
*/
import { store as noticesStore } from '@wordpress/notices';
-import { useDispatch } from '@wordpress/data';
+import { useDispatch, useSelect } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';
import { PluginArea } from '@wordpress/plugins';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { useCallback } from '@wordpress/element';
/**
* Internal dependencies
*/
import Layout from '../layout';
import { unlock } from '../../lock-unlock';
+import { store as editSiteStore } from '../../store';
import { useCommonCommands } from '../../hooks/commands/use-common-commands';
-import useActiveRoute from '../layout/router';
import useSetCommandContext from '../../hooks/commands/use-set-command-context';
import { useRegisterSiteEditorRoutes } from '../site-editor-routes';
+import {
+ currentlyPreviewingTheme,
+ isPreviewingTheme,
+} from '../../utils/is-previewing-theme';
const { RouterProvider } = unlock( routerPrivateApis );
function AppLayout() {
useCommonCommands();
useSetCommandContext();
- useRegisterSiteEditorRoutes();
- const route = useActiveRoute();
- return ;
+ return ;
}
export default function App() {
+ useRegisterSiteEditorRoutes();
const { createErrorNotice } = useDispatch( noticesStore );
-
+ const routes = useSelect( ( select ) => {
+ return unlock( select( editSiteStore ) ).getRoutes();
+ }, [] );
function onPluginAreaError( name ) {
createErrorNotice(
sprintf(
@@ -42,9 +48,29 @@ export default function App() {
)
);
}
+ const beforeNavigate = useCallback( ( { path, query } ) => {
+ if ( ! isPreviewingTheme() ) {
+ return { path, query };
+ }
+
+ return {
+ path,
+ query: {
+ ...query,
+ wp_theme_preview:
+ 'wp_theme_preview' in query
+ ? query.wp_theme_preview
+ : currentlyPreviewingTheme(),
+ },
+ };
+ }, [] );
return (
-
+
diff --git a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js
index 7c88fee0d5b727..1c70c85aed08d3 100644
--- a/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js
+++ b/packages/edit-site/src/components/block-editor/use-editor-iframe-props.js
@@ -12,6 +12,7 @@ import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { store as editorStore } from '@wordpress/editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -21,9 +22,9 @@ import { unlock } from '../../lock-unlock';
const { useLocation, useHistory } = unlock( routerPrivateApis );
export default function useEditorIframeProps() {
- const { params } = useLocation();
+ const { query, path } = useLocation();
const history = useHistory();
- const { canvas = 'view' } = params;
+ const { canvas = 'view' } = query;
const currentPostIsTrashed = useSelect( ( select ) => {
return (
select( editorStore ).getCurrentPostAttribute( 'status' ) ===
@@ -55,13 +56,13 @@ export default function useEditorIframeProps() {
! currentPostIsTrashed
) {
event.preventDefault();
- history.push( { ...params, canvas: 'edit' }, undefined, {
+ history.navigate( addQueryArgs( path, { canvas: 'edit' } ), {
transition: 'canvas-mode-edit-transition',
} );
}
},
onClick: () =>
- history.push( { ...params, canvas: 'edit' }, undefined, {
+ history.navigate( addQueryArgs( path, { canvas: 'edit' } ), {
transition: 'canvas-mode-edit-transition',
} ),
onClickCapture: ( event ) => {
diff --git a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js
index 120b15b8551d3d..8cc7fdaefe2d98 100644
--- a/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js
+++ b/packages/edit-site/src/components/block-editor/use-navigate-to-entity-record.js
@@ -16,7 +16,9 @@ export default function useNavigateToEntityRecord() {
const onNavigateToEntityRecord = useCallback(
( params ) => {
- history.push( { ...params, focusMode: true, canvas: 'edit' } );
+ history.navigate(
+ `/${ params.postType }/${ params.id }?canvas=edit&focusMode=true`
+ );
},
[ history ]
);
diff --git a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js
index 186f4aacf79232..d37987dc3dc420 100644
--- a/packages/edit-site/src/components/block-editor/use-site-editor-settings.js
+++ b/packages/edit-site/src/components/block-editor/use-site-editor-settings.js
@@ -22,11 +22,11 @@ function useNavigateToPreviousEntityRecord() {
const history = useHistory();
const goBack = useMemo( () => {
const isFocusMode =
- location.params.focusMode ||
- ( location.params.postId &&
- FOCUSABLE_ENTITIES.includes( location.params.postType ) );
+ location.query.focusMode ||
+ ( location?.params?.postId &&
+ FOCUSABLE_ENTITIES.includes( location?.params?.postType ) );
const didComeFromEditorCanvas =
- previousLocation?.params.canvas === 'edit';
+ previousLocation?.query.canvas === 'edit';
const showBackButton = isFocusMode && didComeFromEditorCanvas;
return showBackButton ? () => history.back() : undefined;
// `previousLocation` changes when the component updates for any reason, not
@@ -37,8 +37,8 @@ function useNavigateToPreviousEntityRecord() {
}
export function useSpecificEditorSettings() {
- const { params } = useLocation();
- const { canvas = 'view' } = params;
+ const { query } = useLocation();
+ const { canvas = 'view' } = query;
const onNavigateToEntityRecord = useNavigateToEntityRecord();
const { settings } = useSelect( ( select ) => {
const { getSettings } = select( editSiteStore );
diff --git a/packages/edit-site/src/components/dataviews-actions/index.js b/packages/edit-site/src/components/dataviews-actions/index.js
index 09b7597c6cb341..0a7b20c712c820 100644
--- a/packages/edit-site/src/components/dataviews-actions/index.js
+++ b/packages/edit-site/src/components/dataviews-actions/index.js
@@ -31,11 +31,7 @@ export const useEditPostAction = () => {
},
callback( items ) {
const post = items[ 0 ];
- history.push( {
- postId: post.id,
- postType: post.type,
- canvas: 'edit',
- } );
+ history.navigate( `/${ post.type }/${ post.id }?canvas=edit` );
},
} ),
[ history ]
diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js
index 1d115dca7518df..c045bafd8a6839 100644
--- a/packages/edit-site/src/components/editor/index.js
+++ b/packages/edit-site/src/components/editor/index.js
@@ -54,6 +54,7 @@ import {
useResolveEditedEntity,
useSyncDeprecatedEntityIntoState,
} from './use-resolve-edited-entity';
+import { addQueryArgs } from '@wordpress/url';
const { Editor, BackButton } = unlock( editorPrivateApis );
const { useHistory, useLocation } = unlock( routerPrivateApis );
@@ -83,10 +84,44 @@ const siteIconVariants = {
},
};
+function getListPathForPostType( postType ) {
+ switch ( postType ) {
+ case 'navigation':
+ return '/navigation';
+ case 'wp_block':
+ return '/pattern?postType=wp_block';
+ case 'wp_template_part':
+ return '/pattern?postType=wp_template_part';
+ case 'wp_template':
+ return '/template';
+ case 'page':
+ return '/page';
+ case 'post':
+ return '/';
+ }
+ throw 'Unknown post type';
+}
+
+function getNavigationPath( location, postType ) {
+ const { path, name } = location;
+ if (
+ [
+ 'pattern-item',
+ 'template-part-item',
+ 'page-item',
+ 'template-item',
+ 'post-item',
+ ].includes( name )
+ ) {
+ return getListPathForPostType( postType );
+ }
+ return addQueryArgs( path, { canvas: undefined } );
+}
+
export default function EditSiteEditor( { isPostsList = false } ) {
const disableMotion = useReducedMotion();
- const { params } = useLocation();
- const { canvas = 'view' } = params;
+ const location = useLocation();
+ const { canvas = 'view' } = location.query;
const isLoading = useIsSiteEditorLoading();
useAdaptEditorToCanvas( canvas );
const entity = useResolveEditedEntity();
@@ -157,9 +192,11 @@ export default function EditSiteEditor( { isPostsList = false } ) {
case 'move-to-trash':
case 'delete-post':
{
- history.push( {
- postType: items[ 0 ].type,
- } );
+ history.navigate(
+ getListPathForPostType(
+ postWithTemplate ? context.postType : postType
+ )
+ );
}
break;
case 'duplicate-post':
@@ -182,11 +219,9 @@ export default function EditSiteEditor( { isPostsList = false } ) {
{
label: __( 'Edit' ),
onClick: () => {
- history.push( {
- postId: newItem.id,
- postType: newItem.type,
- canvas: 'edit',
- } );
+ history.navigate(
+ `/${ newItem.type }/${ newItem.id }?canvas=edit`
+ );
},
},
],
@@ -196,7 +231,13 @@ export default function EditSiteEditor( { isPostsList = false } ) {
break;
}
},
- [ history, createSuccessNotice ]
+ [
+ postType,
+ context?.postType,
+ postWithTemplate,
+ history,
+ createSuccessNotice,
+ ]
);
// Replace the title and icon displayed in the DocumentBar when there's an overlay visible.
@@ -268,26 +309,20 @@ export default function EditSiteEditor( { isPostsList = false } ) {
// come here through `posts list` and are in focus mode editing a template, template part etc..
if (
isPostsList &&
- params?.focusMode
+ location.query?.focusMode
) {
- history.push(
- {
- page: 'gutenberg-posts-dashboard',
- postType: 'post',
- },
- undefined,
- {
- transition:
- 'canvas-mode-view-transition',
- }
- );
+ history.navigate( '/', {
+ transition:
+ 'canvas-mode-view-transition',
+ } );
} else {
- history.push(
- {
- ...params,
- canvas: undefined,
- },
- undefined,
+ history.navigate(
+ getNavigationPath(
+ location,
+ postWithTemplate
+ ? context.postType
+ : postType
+ ),
{
transition:
'canvas-mode-view-transition',
diff --git a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js
index 4f873738704141..8da076f9f00b71 100644
--- a/packages/edit-site/src/components/editor/use-resolve-edited-entity.js
+++ b/packages/edit-site/src/components/editor/use-resolve-edited-entity.js
@@ -30,8 +30,23 @@ const postTypesWithoutParentTemplate = [
const authorizedPostTypes = [ 'page', 'post' ];
export function useResolveEditedEntity() {
- const { params = {} } = useLocation();
- const { postId, postType } = params;
+ const { name, params = {}, query } = useLocation();
+ const { postId = query?.postId } = params; // Fallback to query param for postId for list view routes.
+ let postType;
+ if ( name === 'navigation-item' ) {
+ postType = NAVIGATION_POST_TYPE;
+ } else if ( name === 'pattern-item' ) {
+ postType = PATTERN_TYPES.user;
+ } else if ( name === 'template-part-item' ) {
+ postType = TEMPLATE_PART_POST_TYPE;
+ } else if ( name === 'template-item' || name === 'templates' ) {
+ postType = TEMPLATE_POST_TYPE;
+ } else if ( name === 'page-item' || name === 'pages' ) {
+ postType = 'page';
+ } else if ( name === 'post-item' || name === 'posts' ) {
+ postType = 'post';
+ }
+
const homePage = useSelect( ( select ) => {
const { getHomePage } = unlock( select( coreDataStore ) );
return getHomePage();
diff --git a/packages/edit-site/src/components/global-styles-sidebar/index.js b/packages/edit-site/src/components/global-styles-sidebar/index.js
index d46346b50dae37..02a29dac5c0b7d 100644
--- a/packages/edit-site/src/components/global-styles-sidebar/index.js
+++ b/packages/edit-site/src/components/global-styles-sidebar/index.js
@@ -28,8 +28,8 @@ const { interfaceStore } = unlock( editorPrivateApis );
const { useLocation } = unlock( routerPrivateApis );
export default function GlobalStylesSidebar() {
- const { params } = useLocation();
- const { canvas = 'view', path } = params;
+ const { query } = useLocation();
+ const { canvas = 'view', name } = query;
const {
shouldClearCanvasContainerView,
isStyleBookOpened,
@@ -133,14 +133,14 @@ export default function GlobalStylesSidebar() {
const previousActiveAreaRef = useRef( null );
useEffect( () => {
- if ( path?.startsWith( '/wp_global_styles' ) && canvas === 'edit' ) {
+ if ( name === 'styles' && canvas === 'edit' ) {
previousActiveAreaRef.current =
getActiveComplementaryArea( 'core' );
enableComplementaryArea( 'core', 'edit-site/global-styles' );
} else if ( previousActiveAreaRef.current ) {
enableComplementaryArea( 'core', previousActiveAreaRef.current );
}
- }, [ path, enableComplementaryArea, canvas, getActiveComplementaryArea ] );
+ }, [ name, enableComplementaryArea, canvas, getActiveComplementaryArea ] );
return (
{
- const { postType, path, categoryType, ...rest } = params;
-
- if ( path === '/wp_template_part/all' ) {
- history.replace( { postType: TEMPLATE_PART_POST_TYPE } );
- }
-
- if ( path === '/page' ) {
- history.replace( {
- postType: 'page',
- ...rest,
- } );
- }
-
- if ( path === '/wp_template' ) {
- history.replace( {
- postType: TEMPLATE_POST_TYPE,
- ...rest,
- } );
- }
-
- if ( path === '/patterns' ) {
- history.replace( {
- postType:
- categoryType === TEMPLATE_PART_POST_TYPE
- ? TEMPLATE_PART_POST_TYPE
- : PATTERN_TYPES.user,
- ...rest,
- } );
- }
-
- if ( path === '/navigation' ) {
- history.replace( {
- postType: NAVIGATION_POST_TYPE,
- ...rest,
- } );
- }
- }, [ history, params ] );
-}
-
-export default function useActiveRoute() {
- const { params } = useLocation();
- useRedirectOldPaths();
- const routes = useSelect( ( select ) => {
- return unlock( select( editSiteStore ) ).getRoutes();
- }, [] );
- return useMemo( () => {
- const matchedRoute = routes.find( ( route ) => route.match( params ) );
- if ( ! matchedRoute ) {
- return {
- key: 404,
- areas: {},
- widths: {},
- };
- }
-
- return {
- name: matchedRoute.name,
- areas: matchedRoute.areas,
- widths: matchedRoute.widths,
- };
- }, [ routes, params ] );
-}
diff --git a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js
index d87737c55326c6..ca7bbf2fa73220 100644
--- a/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js
+++ b/packages/edit-site/src/components/page-patterns/delete-category-menu-item.js
@@ -59,10 +59,9 @@ export default function DeleteCategoryMenuItem( { category, onClose } ) {
);
onClose?.();
- history.push( {
- postType: PATTERN_TYPES.user,
- categoryId: PATTERN_DEFAULT_CATEGORY,
- } );
+ history.navigate(
+ `/pattern?categoryId=${ PATTERN_DEFAULT_CATEGORY }`
+ );
} catch ( error ) {
const errorMessage =
error.message && error.code !== 'unknown_error'
diff --git a/packages/edit-site/src/components/page-patterns/fields.js b/packages/edit-site/src/components/page-patterns/fields.js
index e016dca6cd8557..60e37844b2edb1 100644
--- a/packages/edit-site/src/components/page-patterns/fields.js
+++ b/packages/edit-site/src/components/page-patterns/fields.js
@@ -21,6 +21,7 @@ import {
import { Icon, lockSmall } from '@wordpress/icons';
import { parse } from '@wordpress/blocks';
import { decodeEntities } from '@wordpress/html-entities';
+import { privateApis as routerPrivateApis } from '@wordpress/router';
/**
* Internal dependencies
@@ -32,10 +33,10 @@ import {
OPERATOR_IS,
} from '../../utils/constants';
import { unlock } from '../../lock-unlock';
-import { useLink } from '../routes/link';
import { useAddedBy } from '../page-templates/hooks';
import { defaultGetTitle } from './search-items';
+const { useLink } = unlock( routerPrivateApis );
const { useGlobalStyle } = unlock( blockEditorPrivateApis );
function PreviewWrapper( { item, onClick, ariaDescribedBy, children } ) {
@@ -59,11 +60,11 @@ function PreviewField( { item } ) {
const isUserPattern = item.type === PATTERN_TYPES.user;
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
const [ backgroundColor ] = useGlobalStyle( 'color.background' );
- const { onClick } = useLink( {
- postType: item.type,
- postId: isUserPattern || isTemplatePart ? item.id : item.name,
- canvas: 'edit',
- } );
+ const { onClick } = useLink(
+ `/${ item.type }/${
+ isUserPattern || isTemplatePart ? item.id : item.name
+ }?canvas=edit`
+ );
const blocks = useMemo( () => {
return (
item.blocks ??
@@ -114,11 +115,11 @@ export const previewField = {
function TitleField( { item } ) {
const isUserPattern = item.type === PATTERN_TYPES.user;
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
- const { onClick } = useLink( {
- postType: item.type,
- postId: isUserPattern || isTemplatePart ? item.id : item.name,
- canvas: 'edit',
- } );
+ const { onClick } = useLink(
+ `/${ item.type }/${
+ isUserPattern || isTemplatePart ? item.id : item.name
+ }?canvas=edit`
+ );
const title = decodeEntities( defaultGetTitle( item ) );
return (
diff --git a/packages/edit-site/src/components/page-patterns/index.js b/packages/edit-site/src/components/page-patterns/index.js
index 69ebf66093806a..b6753334887573 100644
--- a/packages/edit-site/src/components/page-patterns/index.js
+++ b/packages/edit-site/src/components/page-patterns/index.js
@@ -72,17 +72,16 @@ const DEFAULT_VIEW = {
export default function DataviewsPatterns() {
const {
- params: { postType, categoryId: categoryIdFromURL },
+ query: { postType = 'wp_block', categoryId: categoryIdFromURL },
} = useLocation();
- const type = postType || PATTERN_TYPES.user;
const categoryId = categoryIdFromURL || PATTERN_DEFAULT_CATEGORY;
const [ view, setView ] = useState( DEFAULT_VIEW );
const previousCategoryId = usePrevious( categoryId );
- const previousPostType = usePrevious( type );
+ const previousPostType = usePrevious( postType );
const viewSyncStatus = view.filters?.find(
( { field } ) => field === 'sync-status'
)?.value;
- const { patterns, isResolving } = usePatterns( type, categoryId, {
+ const { patterns, isResolving } = usePatterns( postType, categoryId, {
search: view.search,
syncStatus: viewSyncStatus,
} );
@@ -108,9 +107,9 @@ export default function DataviewsPatterns() {
const fields = useMemo( () => {
const _fields = [ previewField, titleField ];
- if ( type === PATTERN_TYPES.user ) {
+ if ( postType === PATTERN_TYPES.user ) {
_fields.push( patternStatusField );
- } else if ( type === TEMPLATE_PART_POST_TYPE ) {
+ } else if ( postType === TEMPLATE_PART_POST_TYPE ) {
_fields.push( {
...templatePartAuthorField,
elements: authors,
@@ -118,24 +117,27 @@ export default function DataviewsPatterns() {
}
return _fields;
- }, [ type, authors ] );
+ }, [ postType, authors ] );
// Reset the page number when the category changes.
useEffect( () => {
- if ( previousCategoryId !== categoryId || previousPostType !== type ) {
+ if (
+ previousCategoryId !== categoryId ||
+ previousPostType !== postType
+ ) {
setView( ( prevView ) => ( { ...prevView, page: 1 } ) );
}
- }, [ categoryId, previousCategoryId, previousPostType, type ] );
+ }, [ categoryId, previousCategoryId, previousPostType, postType ] );
const { data, paginationInfo } = useMemo( () => {
// Search is managed server-side as well as filters for patterns.
// However, the author filter in template parts is done client-side.
const viewWithoutFilters = { ...view };
delete viewWithoutFilters.search;
- if ( type !== TEMPLATE_PART_POST_TYPE ) {
+ if ( postType !== TEMPLATE_PART_POST_TYPE ) {
viewWithoutFilters.filters = [];
}
return filterSortAndPaginate( patterns, viewWithoutFilters, fields );
- }, [ patterns, view, fields, type ] );
+ }, [ patterns, view, fields, postType ] );
const dataWithPermissions = useAugmentPatternsWithPermissions( data );
@@ -150,11 +152,11 @@ export default function DataviewsPatterns() {
const editAction = useEditPostAction();
const actions = useMemo( () => {
- if ( type === TEMPLATE_PART_POST_TYPE ) {
+ if ( postType === TEMPLATE_PART_POST_TYPE ) {
return [ editAction, ...templatePartActions ].filter( Boolean );
}
return [ editAction, ...patternActions ].filter( Boolean );
- }, [ editAction, type, templatePartActions, patternActions ] );
+ }, [ editAction, postType, templatePartActions, patternActions ] );
const id = useId();
const settings = usePatternSettings();
// Wrap everything in a block editor provider.
@@ -169,7 +171,7 @@ export default function DataviewsPatterns() {
>
diff --git a/packages/edit-site/src/components/page-templates/fields.js b/packages/edit-site/src/components/page-templates/fields.js
index 69e0596bf49d47..35d7b9714d5be1 100644
--- a/packages/edit-site/src/components/page-templates/fields.js
+++ b/packages/edit-site/src/components/page-templates/fields.js
@@ -16,16 +16,16 @@ import {
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';
import { EditorProvider } from '@wordpress/editor';
+import { privateApis as routerPrivateApis } from '@wordpress/router';
/**
* Internal dependencies
*/
-import { default as Link, useLink } from '../routes/link';
import { useAddedBy } from './hooks';
-
import usePatternSettings from '../page-patterns/use-pattern-settings';
import { unlock } from '../../lock-unlock';
+const { useLink, Link } = unlock( routerPrivateApis );
const { useGlobalStyle } = unlock( blockEditorPrivateApis );
function PreviewField( { item } ) {
@@ -34,11 +34,7 @@ function PreviewField( { item } ) {
const blocks = useMemo( () => {
return parse( item.content.raw );
}, [ item.content.raw ] );
- const { onClick } = useLink( {
- postId: item.id,
- postType: item.type,
- canvas: 'edit',
- } );
+ const { onClick } = useLink( `/${ item.type }/${ item.id }?canvas=edit` );
const isEmpty = ! blocks?.length;
// Wrap everything in a block editor provider to ensure 'styles' that are needed
@@ -80,15 +76,8 @@ export const previewField = {
};
function TitleField( { item } ) {
- const linkProps = {
- params: {
- postId: item.id,
- postType: item.type,
- canvas: 'edit',
- },
- };
return (
-
+
{ decodeEntities( item.title?.rendered ) || __( '(no title)' ) }
);
diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js
index ea026ca53566e8..828867e6f283de 100644
--- a/packages/edit-site/src/components/page-templates/index.js
+++ b/packages/edit-site/src/components/page-templates/index.js
@@ -7,6 +7,7 @@ import { privateApis as corePrivateApis } from '@wordpress/core-data';
import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { privateApis as editorPrivateApis } from '@wordpress/editor';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -93,8 +94,8 @@ const DEFAULT_VIEW = {
};
export default function PageTemplates() {
- const { params } = useLocation();
- const { activeView = 'all', layout, postId } = params;
+ const { path, query } = useLocation();
+ const { activeView = 'all', layout, postId } = query;
const [ selection, setSelection ] = useState( [ postId ] );
const defaultView = useMemo( () => {
@@ -118,8 +119,10 @@ export default function PageTemplates() {
}, [ layout, activeView ] );
const [ view, setView ] = useState( defaultView );
useEffect( () => {
+ const usedType = layout ?? DEFAULT_VIEW.type;
setView( ( currentView ) => ( {
...currentView,
+ type: usedType,
filters:
activeView !== 'all'
? [
@@ -131,7 +134,7 @@ export default function PageTemplates() {
]
: [],
} ) );
- }, [ activeView ] );
+ }, [ activeView, layout ] );
const { records, isResolving: isLoadingData } =
useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, {
@@ -142,13 +145,14 @@ export default function PageTemplates() {
( items ) => {
setSelection( items );
if ( view?.type === LAYOUT_LIST ) {
- history.push( {
- ...params,
- postId: items.length === 1 ? items[ 0 ] : undefined,
- } );
+ history.navigate(
+ addQueryArgs( path, {
+ postId: items.length === 1 ? items[ 0 ] : undefined,
+ } )
+ );
}
},
- [ history, params, view?.type ]
+ [ history, path, view?.type ]
);
const authors = useMemo( () => {
@@ -195,15 +199,16 @@ export default function PageTemplates() {
const onChangeView = useCallback(
( newView ) => {
if ( newView.type !== view.type ) {
- history.push( {
- ...params,
- layout: newView.type,
- } );
+ history.navigate(
+ addQueryArgs( path, {
+ layout: newView.type,
+ } )
+ );
}
setView( newView );
},
- [ view.type, setView, history, params ]
+ [ view.type, setView, history, path ]
);
return (
diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js
index 975809b2ad6106..d58ddbe50758c7 100644
--- a/packages/edit-site/src/components/post-list/index.js
+++ b/packages/edit-site/src/components/post-list/index.js
@@ -13,6 +13,8 @@ import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews';
import { privateApis as editorPrivateApis } from '@wordpress/editor';
import { __ } from '@wordpress/i18n';
import { drawerRight } from '@wordpress/icons';
+import { usePrevious } from '@wordpress/compose';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -31,7 +33,6 @@ import {
import AddNewPostModal from '../add-new-post';
import { unlock } from '../../lock-unlock';
import { useEditPostAction } from '../dataviews-actions';
-import { usePrevious } from '@wordpress/compose';
const { usePostActions, usePostFields } = unlock( editorPrivateApis );
const { useLocation, useHistory } = unlock( routerPrivateApis );
@@ -70,7 +71,8 @@ const getCustomView = ( editedEntityRecord ) => {
*/
function useView( postType ) {
const {
- params: { activeView = 'all', isCustom = 'false', layout },
+ path,
+ query: { activeView = 'all', isCustom = 'false', layout },
} = useLocation();
const history = useHistory();
@@ -112,16 +114,15 @@ function useView( postType ) {
const setViewWithUrlUpdate = useCallback(
( newView ) => {
- const { params } = history.getLocationWithParams();
-
- if ( newView.type === LAYOUT_LIST && ! params?.layout ) {
+ if ( newView.type === LAYOUT_LIST && ! layout ) {
// Skip updating the layout URL param if
// it is not present and the newView.type is LAYOUT_LIST.
- } else if ( newView.type !== params?.layout ) {
- history.push( {
- ...params,
- layout: newView.type,
- } );
+ } else if ( newView.type !== layout ) {
+ history.navigate(
+ addQueryArgs( path, {
+ layout: newView.type,
+ } )
+ );
}
setView( newView );
@@ -137,7 +138,14 @@ function useView( postType ) {
);
}
},
- [ history, isCustom, editEntityRecord, editedEntityRecord?.id ]
+ [
+ history,
+ isCustom,
+ editEntityRecord,
+ editedEntityRecord?.id,
+ layout,
+ path,
+ ]
);
// When layout URL param changes, update the view type
@@ -186,20 +194,20 @@ export default function PostList( { postType } ) {
quickEdit = false,
isCustom,
activeView = 'all',
- } = location.params;
+ } = location.query;
const [ selection, setSelection ] = useState( postId?.split( ',' ) ?? [] );
const onChangeSelection = useCallback(
( items ) => {
setSelection( items );
- const { params } = history.getLocationWithParams();
- if ( ( params.isCustom ?? 'false' ) === 'false' ) {
- history.push( {
- ...params,
- postId: items.join( ',' ),
- } );
+ if ( ( location.query.isCustom ?? 'false' ) === 'false' ) {
+ history.navigate(
+ addQueryArgs( location.path, {
+ postId: items.join( ',' ),
+ } )
+ );
}
},
- [ history ]
+ [ location.path, location.query.isCustom, history ]
);
const getActiveViewFilters = ( views, match ) => {
@@ -311,12 +319,13 @@ export default function PostList( { postType } ) {
useEffect( () => {
if ( postIdWasDeleted ) {
- history.push( {
- ...history.getLocationWithParams().params,
- postId: undefined,
- } );
+ history.navigate(
+ addQueryArgs( location.path, {
+ postId: undefined,
+ } )
+ );
}
- }, [ postIdWasDeleted, history ] );
+ }, [ history, postIdWasDeleted, location.path ] );
const paginationInfo = useMemo(
() => ( {
@@ -355,11 +364,7 @@ export default function PostList( { postType } ) {
const openModal = () => setShowAddPostModal( true );
const closeModal = () => setShowAddPostModal( false );
const handleNewPage = ( { type, id } ) => {
- history.push( {
- postId: id,
- postType: type,
- canvas: 'edit',
- } );
+ history.navigate( `/${ type }/${ id }?canvas=edit` );
closeModal();
};
@@ -401,11 +406,7 @@ export default function PostList( { postType } ) {
onChangeSelection={ onChangeSelection }
isItemClickable={ ( item ) => item.status !== 'trash' }
onClickItem={ ( { id } ) => {
- history.push( {
- postId: id,
- postType,
- canvas: 'edit',
- } );
+ history.navigate( `/${ postType }/${ id }?canvas=edit` );
} }
getItemId={ getItemId }
defaultLayouts={ defaultLayouts }
@@ -419,10 +420,11 @@ export default function PostList( { postType } ) {
icon={ drawerRight }
label={ __( 'Details' ) }
onClick={ () => {
- history.push( {
- ...location.params,
- quickEdit: quickEdit ? undefined : true,
- } );
+ history.navigate(
+ addQueryArgs( location.path, {
+ quickEdit: quickEdit ? undefined : true,
+ } )
+ );
} }
/>
)
diff --git a/packages/edit-site/src/components/posts-app-routes/home.js b/packages/edit-site/src/components/posts-app-routes/home.js
deleted file mode 100644
index ec99cbd8899f1d..00000000000000
--- a/packages/edit-site/src/components/posts-app-routes/home.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import Editor from '../editor';
-import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main';
-import { unlock } from '../../lock-unlock';
-
-const { useLocation } = unlock( routerPrivateApis );
-
-function HomeMobileView() {
- const { params = {} } = useLocation();
- const { canvas = 'view' } = params;
-
- return canvas === 'edit' ? (
-
- ) : (
-
- );
-}
-
-export const homeRoute = {
- name: 'home',
- match: () => {
- return true;
- },
- areas: {
- sidebar: ,
- preview: ,
- mobile: HomeMobileView,
- },
-};
diff --git a/packages/edit-site/src/components/posts-app-routes/index.js b/packages/edit-site/src/components/posts-app-routes/index.js
index e850bbd382200d..3919ea3930d073 100644
--- a/packages/edit-site/src/components/posts-app-routes/index.js
+++ b/packages/edit-site/src/components/posts-app-routes/index.js
@@ -9,21 +9,10 @@ import { useEffect } from '@wordpress/element';
*/
import { unlock } from '../../lock-unlock';
import { store as siteEditorStore } from '../../store';
-import { homeRoute } from './home';
-import { postsListViewQuickEditRoute } from './posts-list-view-quick-edit';
-import { postsListViewRoute } from './posts-list-view';
-import { postsViewQuickEditRoute } from './posts-view-quick-edit';
-import { postsViewRoute } from './posts-view';
-import { postsEditRoute } from './posts-edit';
+import { postsRoute } from './posts';
+import { postItemRoute } from './post-item';
-const routes = [
- postsListViewQuickEditRoute,
- postsListViewRoute,
- postsViewQuickEditRoute,
- postsViewRoute,
- postsEditRoute,
- homeRoute,
-];
+const routes = [ postItemRoute, postsRoute ];
export function useRegisterPostsAppRoutes() {
const registry = useRegistry();
diff --git a/packages/edit-site/src/components/posts-app-routes/posts-edit.js b/packages/edit-site/src/components/posts-app-routes/post-item.js
similarity index 62%
rename from packages/edit-site/src/components/posts-app-routes/posts-edit.js
rename to packages/edit-site/src/components/posts-app-routes/post-item.js
index d3958245595416..54131814f1ae22 100644
--- a/packages/edit-site/src/components/posts-app-routes/posts-edit.js
+++ b/packages/edit-site/src/components/posts-app-routes/post-item.js
@@ -6,25 +6,21 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import PostList from '../post-list';
+import Editor from '../editor';
import DataViewsSidebarContent from '../sidebar-dataviews';
import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import Editor from '../editor';
-export const postsEditRoute = {
- name: 'posts-edit',
- match: ( params ) => {
- return params.postType === 'post' && params.canvas === 'edit';
- },
+export const postItemRoute = {
+ name: 'post-item',
+ path: '/post/:postId',
areas: {
sidebar: (
}
+ content={ }
/>
),
- content: ,
mobile: ,
preview: ,
},
diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js
deleted file mode 100644
index d2434b390ffd9f..00000000000000
--- a/packages/edit-site/src/components/posts-app-routes/posts-list-view-quick-edit.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import { unlock } from '../../lock-unlock';
-import { PostEdit } from '../post-edit';
-import Editor from '../editor';
-
-const { useLocation } = unlock( routerPrivateApis );
-
-function PostQuickEdit() {
- const { params } = useLocation();
- return ;
-}
-
-export const postsListViewQuickEditRoute = {
- name: 'posts-list-view-quick-edit',
- match: ( params ) => {
- return (
- params.isCustom !== 'true' &&
- ( params.layout ?? 'list' ) === 'list' &&
- !! params.quickEdit &&
- params.postType === 'post' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- preview: ,
- edit: ,
- },
- widths: {
- content: 380,
- edit: 380,
- },
-};
diff --git a/packages/edit-site/src/components/posts-app-routes/posts-list-view.js b/packages/edit-site/src/components/posts-app-routes/posts-list-view.js
deleted file mode 100644
index 68aa86c7fb2392..00000000000000
--- a/packages/edit-site/src/components/posts-app-routes/posts-list-view.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import Editor from '../editor';
-
-export const postsListViewRoute = {
- name: 'posts-list-view',
- match: ( params ) => {
- return (
- params.isCustom !== 'true' &&
- ( params.layout ?? 'list' ) === 'list' &&
- ! params.quickEdit &&
- params.postType === 'post' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- preview: ,
- mobile: ,
- },
- widths: {
- content: 380,
- },
-};
diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js b/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js
deleted file mode 100644
index 52e6f9a2d26ef6..00000000000000
--- a/packages/edit-site/src/components/posts-app-routes/posts-view-quick-edit.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import { unlock } from '../../lock-unlock';
-import { PostEdit } from '../post-edit';
-
-const { useLocation } = unlock( routerPrivateApis );
-
-function PostQuickEdit() {
- const { params } = useLocation();
- return ;
-}
-
-export const postsViewQuickEditRoute = {
- name: 'posts-view-quick-edit',
- match: ( params ) => {
- return (
- ( params.isCustom === 'true' ||
- ( params.layout ?? 'list' ) !== 'list' ) &&
- !! params.quickEdit &&
- params.postType === 'post' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- edit: ,
- },
- widths: {
- edit: 380,
- },
-};
diff --git a/packages/edit-site/src/components/posts-app-routes/posts-view.js b/packages/edit-site/src/components/posts-app-routes/posts-view.js
deleted file mode 100644
index 6559991475d278..00000000000000
--- a/packages/edit-site/src/components/posts-app-routes/posts-view.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-
-export const postsViewRoute = {
- name: 'posts-view',
- match: ( params ) => {
- return (
- ( params.isCustom === 'true' ||
- ( params.layout ?? 'list' ) !== 'list' ) &&
- ! params.quickEdit &&
- params.postType === 'post' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/posts-app-routes/posts.js b/packages/edit-site/src/components/posts-app-routes/posts.js
new file mode 100644
index 00000000000000..80af8a75fbc800
--- /dev/null
+++ b/packages/edit-site/src/components/posts-app-routes/posts.js
@@ -0,0 +1,66 @@
+/**
+ * WordPress dependencies
+ */
+import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreen from '../sidebar-navigation-screen';
+import DataViewsSidebarContent from '../sidebar-dataviews';
+import PostList from '../post-list';
+import { unlock } from '../../lock-unlock';
+import { PostEdit } from '../post-edit';
+
+const { useLocation } = unlock( routerPrivateApis );
+
+function MobilePostsView() {
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
+
+ return canvas === 'edit' ? : ;
+}
+
+export const postsRoute = {
+ name: 'posts',
+ path: '/',
+ areas: {
+ sidebar: (
+ }
+ />
+ ),
+ content: ,
+ preview( { query } ) {
+ const isListView =
+ ( query.layout === 'list' || ! query.layout ) &&
+ query.isCustom !== 'true';
+ return isListView ? : undefined;
+ },
+ mobile: ,
+ edit( { query } ) {
+ const hasQuickEdit =
+ ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit;
+ return hasQuickEdit ? (
+
+ ) : undefined;
+ },
+ },
+ widths: {
+ content( { query } ) {
+ const isListView =
+ ( query.layout === 'list' || ! query.layout ) &&
+ query.isCustom !== 'true';
+ return isListView ? 380 : undefined;
+ },
+ edit( { query } ) {
+ const hasQuickEdit =
+ ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit;
+ return hasQuickEdit ? 380 : undefined;
+ },
+ },
+};
diff --git a/packages/edit-site/src/components/posts-app/index.js b/packages/edit-site/src/components/posts-app/index.js
index e6eb90c1680019..ab8cfab99f7628 100644
--- a/packages/edit-site/src/components/posts-app/index.js
+++ b/packages/edit-site/src/components/posts-app/index.js
@@ -2,6 +2,7 @@
* WordPress dependencies
*/
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { useSelect } from '@wordpress/data';
/**
* Internal dependencies
@@ -9,20 +10,18 @@ import { privateApis as routerPrivateApis } from '@wordpress/router';
import Layout from '../layout';
import { useRegisterPostsAppRoutes } from '../posts-app-routes';
import { unlock } from '../../lock-unlock';
-import useActiveRoute from '../layout/router';
+import { store as editSiteStore } from '../../store';
const { RouterProvider } = unlock( routerPrivateApis );
-function PostsLayout() {
- useRegisterPostsAppRoutes();
- const route = useActiveRoute();
- return ;
-}
-
export default function PostsApp() {
+ useRegisterPostsAppRoutes();
+ const routes = useSelect( ( select ) => {
+ return unlock( select( editSiteStore ) ).getRoutes();
+ }, [] );
return (
-
-
+
+
);
}
diff --git a/packages/edit-site/src/components/resizable-frame/index.js b/packages/edit-site/src/components/resizable-frame/index.js
index 95ccfe4fdd966f..99f650971112fb 100644
--- a/packages/edit-site/src/components/resizable-frame/index.js
+++ b/packages/edit-site/src/components/resizable-frame/index.js
@@ -20,6 +20,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
+import { addQueryArgs } from '@wordpress/url';
const { useLocation, useHistory } = unlock( routerPrivateApis );
@@ -88,8 +89,8 @@ function ResizableFrame( {
innerContentStyle,
} ) {
const history = useHistory();
- const { params } = useLocation();
- const { canvas = 'view' } = params;
+ const { path, query } = useLocation();
+ const { canvas = 'view' } = query;
const disableMotion = useReducedMotion();
const [ frameSize, setFrameSize ] = useState( INITIAL_FRAME_SIZE );
// The width of the resizable frame when a new resize gesture starts.
@@ -158,12 +159,10 @@ function ResizableFrame( {
setFrameSize( INITIAL_FRAME_SIZE );
} else {
// Trigger full screen if the frame is resized far enough to the left.
- history.push(
- {
- ...params,
+ history.navigate(
+ addQueryArgs( path, {
canvas: 'edit',
- },
- undefined,
+ } ),
{
transition: 'canvas-mode-edit-transition',
}
diff --git a/packages/edit-site/src/components/routes/link.js b/packages/edit-site/src/components/routes/link.js
deleted file mode 100644
index a34b37943a0799..00000000000000
--- a/packages/edit-site/src/components/routes/link.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { addQueryArgs, getQueryArgs, removeQueryArgs } from '@wordpress/url';
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import { unlock } from '../../lock-unlock';
-import {
- isPreviewingTheme,
- currentlyPreviewingTheme,
-} from '../../utils/is-previewing-theme';
-
-const { useHistory } = unlock( routerPrivateApis );
-
-export function useLink( params, state, shouldReplace = false ) {
- const history = useHistory();
- function onClick( event ) {
- event?.preventDefault();
-
- if ( shouldReplace ) {
- history.replace( params, state );
- } else {
- history.push( params, state );
- }
- }
-
- const currentArgs = getQueryArgs( window.location.href );
- const currentUrlWithoutArgs = removeQueryArgs(
- window.location.href,
- ...Object.keys( currentArgs )
- );
-
- let extraParams = {};
- if ( isPreviewingTheme() ) {
- extraParams = {
- wp_theme_preview: currentlyPreviewingTheme(),
- };
- }
-
- const newUrl = addQueryArgs( currentUrlWithoutArgs, {
- ...params,
- ...extraParams,
- } );
-
- return {
- href: newUrl,
- onClick,
- };
-}
-
-export default function Link( {
- params = {},
- state,
- replace: shouldReplace = false,
- children,
- ...props
-} ) {
- const { href, onClick } = useLink( params, state, shouldReplace );
-
- return (
-
- { children }
-
- );
-}
diff --git a/packages/edit-site/src/components/save-panel/index.js b/packages/edit-site/src/components/save-panel/index.js
index b77e5a9a1a10ba..81a0f99557df07 100644
--- a/packages/edit-site/src/components/save-panel/index.js
+++ b/packages/edit-site/src/components/save-panel/index.js
@@ -90,8 +90,8 @@ const _EntitiesSavedStates = ( { onClose, renderDialog = undefined } ) => {
};
export default function SavePanel() {
- const { params } = useLocation();
- const { canvas = 'view' } = params;
+ const { query } = useLocation();
+ const { canvas = 'view' } = query;
const { isSaveViewOpen, isDirty, isSaving } = useSelect( ( select ) => {
const {
__experimentalGetDirtyEntityRecords,
diff --git a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js
index 62956ccd18960d..815de181a9dde0 100644
--- a/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js
+++ b/packages/edit-site/src/components/sidebar-dataviews/add-new-view.js
@@ -14,6 +14,7 @@ import { store as coreStore } from '@wordpress/core-data';
import { useState } from '@wordpress/element';
import { plus } from '@wordpress/icons';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -22,10 +23,11 @@ import SidebarNavigationItem from '../sidebar-navigation-item';
import { useDefaultViews } from './default-views';
import { unlock } from '../../lock-unlock';
-const { useHistory } = unlock( routerPrivateApis );
+const { useLocation, useHistory } = unlock( routerPrivateApis );
function AddNewItemModalContent( { type, setIsAdding } ) {
const history = useHistory();
+ const { path } = useLocation();
const { saveEntityRecord } = useDispatch( coreStore );
const [ title, setTitle ] = useState( '' );
const [ isSaving, setIsSaving ] = useState( false );
@@ -64,14 +66,12 @@ function AddNewItemModalContent( { type, setIsAdding } ) {
content: JSON.stringify( defaultViews[ 0 ].view ),
}
);
- const {
- params: { postType },
- } = history.getLocationWithParams();
- history.push( {
- postType,
- activeView: savedRecord.id,
- isCustom: 'true',
- } );
+ history.navigate(
+ addQueryArgs( path, {
+ activeView: savedRecord.id,
+ isCustom: 'true',
+ } )
+ );
setIsSaving( false );
setIsAdding( false );
} }
diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js
index 1e12d6706d81b5..b98f8b80938d68 100644
--- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js
+++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js
@@ -9,11 +9,11 @@ import clsx from 'clsx';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { __experimentalHStack as HStack } from '@wordpress/components';
import { VIEW_LAYOUTS } from '@wordpress/dataviews';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
*/
-import { useLink } from '../routes/link';
import SidebarNavigationItem from '../sidebar-navigation-item';
import { unlock } from '../../lock-unlock';
const { useLocation } = unlock( routerPrivateApis );
@@ -28,9 +28,7 @@ export default function DataViewItem( {
isCustom,
suffix,
} ) {
- const {
- params: { postType },
- } = useLocation();
+ const { path } = useLocation();
const iconToUse =
icon || VIEW_LAYOUTS.find( ( v ) => v.type === type ).icon;
@@ -39,12 +37,11 @@ export default function DataViewItem( {
if ( activeView === 'all' ) {
activeView = undefined;
}
- const linkInfo = useLink( {
- postType,
+ const query = {
layout: type,
activeView,
isCustom: isCustom ? 'true' : undefined,
- } );
+ };
return (
{ title }
diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js
index 86420c4eec1d1f..410767650c6f36 100644
--- a/packages/edit-site/src/components/sidebar-dataviews/index.js
+++ b/packages/edit-site/src/components/sidebar-dataviews/index.js
@@ -14,9 +14,9 @@ import CustomDataViewsList from './custom-dataviews-list';
const { useLocation } = unlock( routerPrivateApis );
-export default function DataViewsSidebarContent() {
+export default function DataViewsSidebarContent( { postType } ) {
const {
- params: { postType, activeView = 'all', isCustom = 'false' },
+ query: { activeView = 'all', isCustom = 'false' },
} = useLocation();
const defaultViews = useDefaultViews( { postType } );
if ( ! postType ) {
diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
index 342fb1b5db52d2..980f20c49821b0 100644
--- a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
+++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
@@ -9,6 +9,7 @@ import {
Button,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -21,7 +22,6 @@ import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants';
const { useLocation, useHistory } = unlock( routerPrivateApis );
const { Menu } = unlock( componentsPrivateApis );
-const GLOBAL_STYLES_PATH_PREFIX = '/wp_global_styles';
const GlobalStylesPageActions = ( {
isStyleBookOpened,
@@ -63,28 +63,23 @@ const GlobalStylesPageActions = ( {
};
export default function GlobalStylesUIWrapper() {
- const { params } = useLocation();
+ const { path, query } = useLocation();
const history = useHistory();
- const { canvas = 'view' } = params;
+ const { canvas = 'view' } = query;
const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( false );
const isMobileViewport = useViewportMatch( 'medium', '<' );
- const pathWithPrefix = params.path;
- const [ path, onPathChange ] = useMemo( () => {
- const processedPath = pathWithPrefix.substring(
- GLOBAL_STYLES_PATH_PREFIX.length
- );
+ const [ section, onChangeSection ] = useMemo( () => {
return [
- processedPath ? processedPath : '/',
- ( newPath ) => {
- history.push( {
- path:
- ! newPath || newPath === '/'
- ? GLOBAL_STYLES_PATH_PREFIX
- : `${ GLOBAL_STYLES_PATH_PREFIX }${ newPath }`,
- } );
+ query.section ?? '/',
+ ( updatedSection ) => {
+ history.navigate(
+ addQueryArgs( path, {
+ section: updatedSection,
+ } )
+ );
},
];
- }, [ pathWithPrefix, history ] );
+ }, [ path, query.section, history ] );
return (
<>
@@ -100,7 +95,10 @@ export default function GlobalStylesUIWrapper() {
className="edit-site-styles"
title={ __( 'Styles' ) }
>
-
+
{ canvas === 'view' && isStyleBookOpened && (
{
if (
STYLE_BOOK_COLOR_GROUPS.find(
@@ -129,17 +123,17 @@ export default function GlobalStylesUIWrapper() {
)
) {
// Go to color palettes Global Styles.
- onPathChange( '/colors/palette' );
+ onChangeSection( '/colors/palette' );
return;
}
if ( blockName === 'typography' ) {
// Go to typography Global Styles.
- onPathChange( '/typography' );
+ onChangeSection( '/typography' );
return;
}
// Now go to the selected block.
- onPathChange(
+ onChangeSection(
`/blocks/${ encodeURIComponent( blockName ) }`
);
} }
diff --git a/packages/edit-site/src/components/sidebar-navigation-item/index.js b/packages/edit-site/src/components/sidebar-navigation-item/index.js
index 80f06d7e93133b..4bde94dcbbeb4d 100644
--- a/packages/edit-site/src/components/sidebar-navigation-item/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-item/index.js
@@ -22,7 +22,7 @@ import { useContext } from '@wordpress/element';
import { unlock } from '../../lock-unlock';
import { SidebarNavigationContext } from '../sidebar';
-const { useHistory } = unlock( routerPrivateApis );
+const { useHistory, useLink } = unlock( routerPrivateApis );
export default function SidebarNavigationItem( {
className,
@@ -30,7 +30,7 @@ export default function SidebarNavigationItem( {
withChevron = false,
suffix,
uid,
- params,
+ to,
onClick,
children,
...props
@@ -42,12 +42,13 @@ export default function SidebarNavigationItem( {
if ( onClick ) {
onClick( e );
navigate( 'forward' );
- } else if ( params ) {
+ } else if ( to ) {
e.preventDefault();
- history.push( params );
+ history.navigate( to );
navigate( 'forward', `[id="${ uid }"]` );
}
}
+ const linkProps = useLink( to );
return (
-
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
index 72671714479ac0..4023ba436b8659 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
@@ -7,6 +7,7 @@ import { store as coreStore } from '@wordpress/core-data';
import { useCallback } from '@wordpress/element';
import { store as preferencesStore } from '@wordpress/preferences';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -22,7 +23,7 @@ import { MainSidebarNavigationContent } from '../sidebar-navigation-screen-main'
const { useLocation, useHistory } = unlock( routerPrivateApis );
export function SidebarNavigationItemGlobalStyles( props ) {
- const { params } = useLocation();
+ const { name } = useLocation();
const hasGlobalStyleVariations = useSelect(
( select ) =>
!! select(
@@ -34,11 +35,9 @@ export function SidebarNavigationItemGlobalStyles( props ) {
return (
);
}
@@ -47,7 +46,7 @@ export function SidebarNavigationItemGlobalStyles( props ) {
export default function SidebarNavigationScreenGlobalStyles() {
const history = useHistory();
- const { params } = useLocation();
+ const { path } = useLocation();
const {
revisions,
isLoading: isLoadingRevisions,
@@ -60,21 +59,14 @@ export default function SidebarNavigationScreenGlobalStyles() {
const { set: setPreference } = useDispatch( preferencesStore );
const openGlobalStyles = useCallback( async () => {
- history.push(
- {
- ...params,
- canvas: 'edit',
- },
- undefined,
- {
- transition: 'canvas-mode-edit-transition',
- }
- );
+ history.navigate( addQueryArgs( path, { canvas: 'edit' } ), {
+ transition: 'canvas-mode-edit-transition',
+ } );
return Promise.all( [
setPreference( 'core', 'distractionFree', false ),
openGeneralSidebar( 'edit-site/global-styles' ),
] );
- }, [ history, params, openGeneralSidebar, setPreference ] );
+ }, [ path, history, openGeneralSidebar, setPreference ] );
const openRevisions = useCallback( async () => {
await openGlobalStyles();
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js
index 49e60d44047326..1db651631c53d4 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js
@@ -15,18 +15,13 @@ import SidebarNavigationItem from '../sidebar-navigation-item';
import { SidebarNavigationItemGlobalStyles } from '../sidebar-navigation-screen-global-styles';
import { unlock } from '../../lock-unlock';
import { store as editSiteStore } from '../../store';
-import {
- NAVIGATION_POST_TYPE,
- TEMPLATE_POST_TYPE,
- PATTERN_TYPES,
-} from '../../utils/constants';
export function MainSidebarNavigationContent() {
return (
@@ -40,7 +35,7 @@ export function MainSidebarNavigationContent() {
@@ -48,7 +43,7 @@ export function MainSidebarNavigationContent() {
@@ -56,7 +51,7 @@ export function MainSidebarNavigationContent() {
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js
index 6b85e088817edf..a07167413ae119 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/more-menu.js
@@ -58,11 +58,9 @@ export default function ScreenNavigationMoreMenu( props ) {
);
}
-export default function DataviewsTemplatesSidebarContent( {
- activeView,
- title,
-} ) {
+export default function DataviewsTemplatesSidebarContent() {
+ const {
+ query: { activeView = 'all' },
+ } = useLocation();
const { records } = useEntityRecords( 'postType', TEMPLATE_POST_TYPE, {
per_page: -1,
} );
@@ -52,13 +57,13 @@ export default function DataviewsTemplatesSidebarContent( {
return (
-
+ aria-current={ activeView === 'all' }
+ >
+ { __( 'All templates' ) }
+
{ firstItemPerAuthorText.map( ( template ) => {
return (
- }
+ content={ }
/>
);
}
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
index 0080964310525b..c6b3742a3fd8bc 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
@@ -83,7 +83,7 @@ export default function SidebarNavigationScreen( {
{ ! isRoot && (
{
- history.push( backPath );
+ history.navigate( backPath );
navigate( 'back' );
} }
icon={ icon }
@@ -97,7 +97,7 @@ export default function SidebarNavigationScreen( {
label={
dashboardLinkText || __( 'Go to the Dashboard' )
}
- href={ dashboardLink || 'index.php' }
+ href={ dashboardLink }
/>
) }
{
- return params.canvas === 'edit';
- },
- areas: {
- sidebar: ,
- preview: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/home-view.js b/packages/edit-site/src/components/site-editor-routes/home.js
similarity index 66%
rename from packages/edit-site/src/components/site-editor-routes/home-view.js
rename to packages/edit-site/src/components/site-editor-routes/home.js
index 63d3d021e82083..3b6230e6b6c38d 100644
--- a/packages/edit-site/src/components/site-editor-routes/home-view.js
+++ b/packages/edit-site/src/components/site-editor-routes/home.js
@@ -4,13 +4,12 @@
import Editor from '../editor';
import SidebarNavigationScreenMain from '../sidebar-navigation-screen-main';
-export const homeViewRoute = {
- name: 'home-view',
- match: ( params ) => {
- return params.canvas !== 'edit';
- },
+export const homeRoute = {
+ name: 'home',
+ path: '/',
areas: {
sidebar: ,
preview: ,
+ mobile: ,
},
};
diff --git a/packages/edit-site/src/components/site-editor-routes/index.js b/packages/edit-site/src/components/site-editor-routes/index.js
index 4887436dc2ed16..bac2fa302b5cf5 100644
--- a/packages/edit-site/src/components/site-editor-routes/index.js
+++ b/packages/edit-site/src/components/site-editor-routes/index.js
@@ -9,42 +9,30 @@ import { useEffect } from '@wordpress/element';
*/
import { unlock } from '../../lock-unlock';
import { store as siteEditorStore } from '../../store';
-import { homeViewRoute } from './home-view';
-import { homeEditRoute } from './home-edit';
-import { navigationViewRoute } from './navigation-view';
-import { navigationEditRoute } from './navigation-edit';
-import { navigationItemEditRoute } from './navigation-item-edit';
-import { navigationItemViewRoute } from './navigation-item-view';
-import { stylesViewRoute } from './styles-view';
-import { patternsEditRoute } from './patterns-edit';
-import { patternsViewRoute } from './patterns-view';
-import { templatesEditRoute } from './templates-edit';
-import { templatesListViewRoute } from './templates-list-view';
-import { templatesViewRoute } from './templates-view';
-import { pagesViewRoute } from './pages-view';
-import { pagesEditRoute } from './pages-edit';
-import { pagesListViewRoute } from './pages-list-view';
-import { pagesListViewQuickEditRoute } from './pages-list-view-quick-edit';
-import { pagesViewQuickEditRoute } from './pages-view-quick-edit';
+import { homeRoute } from './home';
+import { stylesRoute } from './styles';
+import { navigationRoute } from './navigation';
+import { navigationItemRoute } from './navigation-item';
+import { patternsRoute } from './patterns';
+import { patternItemRoute } from './pattern-item';
+import { templatePartItemRoute } from './template-part-item';
+import { templatesRoute } from './templates';
+import { templateItemRoute } from './template-item';
+import { pagesRoute } from './pages';
+import { pageItemRoute } from './page-item';
const routes = [
- pagesListViewQuickEditRoute,
- pagesListViewRoute,
- pagesViewQuickEditRoute,
- pagesViewRoute,
- pagesEditRoute,
- templatesEditRoute,
- templatesListViewRoute,
- templatesViewRoute,
- patternsViewRoute,
- patternsEditRoute,
- stylesViewRoute,
- navigationItemViewRoute,
- navigationItemEditRoute,
- navigationViewRoute,
- navigationEditRoute,
- homeViewRoute,
- homeEditRoute,
+ pageItemRoute,
+ pagesRoute,
+ templateItemRoute,
+ templatesRoute,
+ templatePartItemRoute,
+ patternItemRoute,
+ patternsRoute,
+ navigationItemRoute,
+ navigationRoute,
+ stylesRoute,
+ homeRoute,
];
export function useRegisterSiteEditorRoutes() {
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-edit.js
deleted file mode 100644
index fdba963c41d0cb..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/navigation-edit.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Internal dependencies
- */
-import { NAVIGATION_POST_TYPE } from '../../utils/constants';
-import Editor from '../editor';
-import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus';
-
-export const navigationEditRoute = {
- name: 'navigation-edit',
- match: ( params ) => {
- return (
- params.postType === NAVIGATION_POST_TYPE &&
- ! params.postId &&
- params.canvas === 'edit'
- );
- },
- areas: {
- sidebar: ,
- preview: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js
deleted file mode 100644
index b03cdbd995ac7c..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/navigation-item-edit.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Internal dependencies
- */
-import { NAVIGATION_POST_TYPE } from '../../utils/constants';
-import Editor from '../editor';
-import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu';
-
-export const navigationItemEditRoute = {
- name: 'navigation-item-edit',
- match: ( params ) => {
- return (
- params.postType === NAVIGATION_POST_TYPE &&
- !! params.postId &&
- params.canvas === 'edit'
- );
- },
- areas: {
- sidebar: (
-
- ),
- preview: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js
deleted file mode 100644
index d04a03a8f9df38..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/navigation-item-view.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Internal dependencies
- */
-import { NAVIGATION_POST_TYPE } from '../../utils/constants';
-import Editor from '../editor';
-import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu';
-
-export const navigationItemViewRoute = {
- name: 'navigation-item-view',
- match: ( params ) => {
- return (
- params.postType === NAVIGATION_POST_TYPE &&
- !! params.postId &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
-
- ),
- preview: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-item.js b/packages/edit-site/src/components/site-editor-routes/navigation-item.js
new file mode 100644
index 00000000000000..76983d8ff8daa4
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/navigation-item.js
@@ -0,0 +1,39 @@
+/**
+ * WordPress dependencies
+ */
+import { privateApis as routerPrivateApis } from '@wordpress/router';
+
+/**
+ * Internal dependencies
+ */
+import { NAVIGATION_POST_TYPE } from '../../utils/constants';
+import Editor from '../editor';
+import SidebarNavigationScreenNavigationMenu from '../sidebar-navigation-screen-navigation-menu';
+import { unlock } from '../../lock-unlock';
+
+const { useLocation } = unlock( routerPrivateApis );
+
+function MobileNavigationItemView() {
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
+
+ return canvas === 'edit' ? (
+
+ ) : (
+
+ );
+}
+
+export const navigationItemRoute = {
+ name: 'navigation-item',
+ path: '/wp_navigation/:postId',
+ areas: {
+ sidebar: (
+
+ ),
+ preview: ,
+ mobile: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation-view.js b/packages/edit-site/src/components/site-editor-routes/navigation-view.js
deleted file mode 100644
index 59c38a2f1d099a..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/navigation-view.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Internal dependencies
- */
-import { NAVIGATION_POST_TYPE } from '../../utils/constants';
-import Editor from '../editor';
-import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus';
-
-export const navigationViewRoute = {
- name: 'navigation-view',
- match: ( params ) => {
- return (
- params.postType === NAVIGATION_POST_TYPE &&
- ! params.postId &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: ,
- preview: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/navigation.js b/packages/edit-site/src/components/site-editor-routes/navigation.js
new file mode 100644
index 00000000000000..4c435e78a495f2
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/navigation.js
@@ -0,0 +1,34 @@
+/**
+ * WordPress dependencies
+ */
+import { privateApis as routerPrivateApis } from '@wordpress/router';
+
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreenNavigationMenus from '../sidebar-navigation-screen-navigation-menus';
+import { unlock } from '../../lock-unlock';
+
+const { useLocation } = unlock( routerPrivateApis );
+
+function MobileNavigationView() {
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
+
+ return canvas === 'edit' ? (
+
+ ) : (
+
+ );
+}
+
+export const navigationRoute = {
+ name: 'navigation',
+ path: '/navigation',
+ areas: {
+ sidebar: ,
+ preview: ,
+ mobile: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/pages-edit.js b/packages/edit-site/src/components/site-editor-routes/page-item.js
similarity index 54%
rename from packages/edit-site/src/components/site-editor-routes/pages-edit.js
rename to packages/edit-site/src/components/site-editor-routes/page-item.js
index ef4c7efbfb09c2..c20720316b10e0 100644
--- a/packages/edit-site/src/components/site-editor-routes/pages-edit.js
+++ b/packages/edit-site/src/components/site-editor-routes/page-item.js
@@ -6,29 +6,21 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import PostList from '../post-list';
+import Editor from '../editor';
import DataViewsSidebarContent from '../sidebar-dataviews';
import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import Editor from '../editor';
-function PageList() {
- return ;
-}
-
-export const pagesEditRoute = {
- name: 'pages-edit',
- match: ( params ) => {
- return params.postType === 'page' && params.canvas === 'edit';
- },
+export const pageItemRoute = {
+ name: 'page-item',
+ path: '/page/:postId',
areas: {
sidebar: (
}
+ backPath="/"
+ content={ }
/>
),
- content: ,
mobile: ,
preview: ,
},
diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js
deleted file mode 100644
index 9eb33e05a99bb0..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/pages-list-view-quick-edit.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import { unlock } from '../../lock-unlock';
-import { PostEdit } from '../post-edit';
-import Editor from '../editor';
-
-const { useLocation } = unlock( routerPrivateApis );
-
-function PageList() {
- return ;
-}
-
-function PageQuickEdit() {
- const { params } = useLocation();
- return ;
-}
-
-export const pagesListViewQuickEditRoute = {
- name: 'pages-list-view-quick-edit',
- match: ( params ) => {
- return (
- params.isCustom !== 'true' &&
- ( params.layout ?? 'list' ) === 'list' &&
- !! params.quickEdit &&
- params.postType === 'page' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- preview: ,
- edit: ,
- },
- widths: {
- content: 380,
- edit: 380,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/pages-list-view.js b/packages/edit-site/src/components/site-editor-routes/pages-list-view.js
deleted file mode 100644
index 74b39848e83f2b..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/pages-list-view.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import Editor from '../editor';
-
-function PageList() {
- return ;
-}
-
-export const pagesListViewRoute = {
- name: 'pages-list-view',
- match: ( params ) => {
- return (
- params.isCustom !== 'true' &&
- ( params.layout ?? 'list' ) === 'list' &&
- ! params.quickEdit &&
- params.postType === 'page' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- preview: ,
- mobile: ,
- },
- widths: {
- content: 380,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js b/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js
deleted file mode 100644
index 907054364c8a93..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/pages-view-quick-edit.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { privateApis as routerPrivateApis } from '@wordpress/router';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-import { unlock } from '../../lock-unlock';
-import { PostEdit } from '../post-edit';
-
-const { useLocation } = unlock( routerPrivateApis );
-
-function PageList() {
- return ;
-}
-
-function PageQuickEdit() {
- const { params } = useLocation();
- return ;
-}
-
-export const pagesViewQuickEditRoute = {
- name: 'pages-view-quick-edit',
- match: ( params ) => {
- return (
- ( params.isCustom === 'true' ||
- ( params.layout ?? 'list' ) !== 'list' ) &&
- !! params.quickEdit &&
- params.postType === 'page' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- edit: ,
- },
- widths: {
- edit: 380,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/pages-view.js b/packages/edit-site/src/components/site-editor-routes/pages-view.js
deleted file mode 100644
index df7e211022cacf..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/pages-view.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import PostList from '../post-list';
-import DataViewsSidebarContent from '../sidebar-dataviews';
-import SidebarNavigationScreen from '../sidebar-navigation-screen';
-
-function PageList() {
- return ;
-}
-
-export const pagesViewRoute = {
- name: 'pages-view',
- match: ( params ) => {
- return (
- ( params.isCustom === 'true' ||
- ( params.layout ?? 'list' ) !== 'list' ) &&
- ! params.quickEdit &&
- params.postType === 'page' &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: (
- }
- />
- ),
- content: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/pages.js b/packages/edit-site/src/components/site-editor-routes/pages.js
new file mode 100644
index 00000000000000..e8c55cd10307e1
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/pages.js
@@ -0,0 +1,66 @@
+/**
+ * WordPress dependencies
+ */
+import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreen from '../sidebar-navigation-screen';
+import DataViewsSidebarContent from '../sidebar-dataviews';
+import PostList from '../post-list';
+import { unlock } from '../../lock-unlock';
+import { PostEdit } from '../post-edit';
+
+const { useLocation } = unlock( routerPrivateApis );
+
+function MobilePagesView() {
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
+
+ return canvas === 'edit' ? : ;
+}
+
+export const pagesRoute = {
+ name: 'pages',
+ path: '/page',
+ areas: {
+ sidebar: (
+ }
+ />
+ ),
+ content: ,
+ preview( { query } ) {
+ const isListView =
+ ( query.layout === 'list' || ! query.layout ) &&
+ query.isCustom !== 'true';
+ return isListView ? : undefined;
+ },
+ mobile: ,
+ edit( { query } ) {
+ const hasQuickEdit =
+ ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit;
+ return hasQuickEdit ? (
+
+ ) : undefined;
+ },
+ },
+ widths: {
+ content( { query } ) {
+ const isListView =
+ ( query.layout === 'list' || ! query.layout ) &&
+ query.isCustom !== 'true';
+ return isListView ? 380 : undefined;
+ },
+ edit( { query } ) {
+ const hasQuickEdit =
+ ( query.layout ?? 'list' ) === 'list' && !! query.quickEdit;
+ return hasQuickEdit ? 380 : undefined;
+ },
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/pattern-item.js b/packages/edit-site/src/components/site-editor-routes/pattern-item.js
new file mode 100644
index 00000000000000..c4cbcf871f3686
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/pattern-item.js
@@ -0,0 +1,15 @@
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns';
+
+export const patternItemRoute = {
+ name: 'pattern-item',
+ path: '/wp_block/:postId',
+ areas: {
+ sidebar: ,
+ mobile: ,
+ preview: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-edit.js b/packages/edit-site/src/components/site-editor-routes/patterns-edit.js
deleted file mode 100644
index eaf1fd68020181..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/patterns-edit.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Internal dependencies
- */
-import Editor from '../editor';
-import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns';
-import PagePatterns from '../page-patterns';
-import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants';
-
-export const patternsEditRoute = {
- name: 'patterns-edit',
- match: ( params ) => {
- return (
- [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes(
- params.postType
- ) && params.canvas === 'edit'
- );
- },
- areas: {
- sidebar: ,
- content: ,
- mobile: ,
- preview: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/patterns-view.js b/packages/edit-site/src/components/site-editor-routes/patterns-view.js
deleted file mode 100644
index 468f7f14abc139..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/patterns-view.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Internal dependencies
- */
-import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns';
-import PagePatterns from '../page-patterns';
-import { PATTERN_TYPES, TEMPLATE_PART_POST_TYPE } from '../../utils/constants';
-
-export const patternsViewRoute = {
- name: 'patterns-view',
- match: ( params ) => {
- return (
- [ TEMPLATE_PART_POST_TYPE, PATTERN_TYPES.user ].includes(
- params.postType
- ) && params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: ,
- content: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/patterns.js b/packages/edit-site/src/components/site-editor-routes/patterns.js
new file mode 100644
index 00000000000000..48207cfe1c1d2c
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/patterns.js
@@ -0,0 +1,15 @@
+/**
+ * Internal dependencies
+ */
+import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns';
+import PagePatterns from '../page-patterns';
+
+export const patternsRoute = {
+ name: 'patterns',
+ path: '/pattern',
+ areas: {
+ sidebar: ,
+ content: ,
+ mobile: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/styles-view.js b/packages/edit-site/src/components/site-editor-routes/styles.js
similarity index 58%
rename from packages/edit-site/src/components/site-editor-routes/styles-view.js
rename to packages/edit-site/src/components/site-editor-routes/styles.js
index cc9411eb8144c0..17e4a3c064d023 100644
--- a/packages/edit-site/src/components/site-editor-routes/styles-view.js
+++ b/packages/edit-site/src/components/site-editor-routes/styles.js
@@ -5,18 +5,12 @@ import Editor from '../editor';
import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles';
import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper';
-export const stylesViewRoute = {
- name: 'styles-view',
- match: ( params ) => {
- return (
- params.path &&
- params.path.startsWith( '/wp_global_styles' ) &&
- params.canvas !== 'edit'
- );
- },
+export const stylesRoute = {
+ name: 'styles',
+ path: '/styles',
areas: {
content: ,
- sidebar: ,
+ sidebar: ,
preview: ,
mobile: ,
},
diff --git a/packages/edit-site/src/components/site-editor-routes/template-item.js b/packages/edit-site/src/components/site-editor-routes/template-item.js
new file mode 100644
index 00000000000000..8ad3ab2b699904
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/template-item.js
@@ -0,0 +1,15 @@
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse';
+
+export const templateItemRoute = {
+ name: 'template-item',
+ path: '/wp_template/*postId',
+ areas: {
+ sidebar: ,
+ mobile: ,
+ preview: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/template-part-item.js b/packages/edit-site/src/components/site-editor-routes/template-part-item.js
new file mode 100644
index 00000000000000..a2b21cf23f808d
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/template-part-item.js
@@ -0,0 +1,15 @@
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreenPatterns from '../sidebar-navigation-screen-patterns';
+
+export const templatePartItemRoute = {
+ name: 'template-part-item',
+ path: '/wp_template_part/*postId',
+ areas: {
+ sidebar: ,
+ mobile: ,
+ preview: ,
+ },
+};
diff --git a/packages/edit-site/src/components/site-editor-routes/templates-edit.js b/packages/edit-site/src/components/site-editor-routes/templates-edit.js
deleted file mode 100644
index 488e9decc1888c..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/templates-edit.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Internal dependencies
- */
-import { TEMPLATE_POST_TYPE } from '../../utils/constants';
-import PageTemplates from '../page-templates';
-import Editor from '../editor';
-import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse';
-
-export const templatesEditRoute = {
- name: 'templates-edit',
- match: ( params ) => {
- return (
- params.postType === TEMPLATE_POST_TYPE && params.canvas === 'edit'
- );
- },
- areas: {
- sidebar: ,
- content: ,
- mobile: ,
- preview: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/templates-list-view.js b/packages/edit-site/src/components/site-editor-routes/templates-list-view.js
deleted file mode 100644
index 7cdda1b13c0b47..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/templates-list-view.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Internal dependencies
- */
-import { TEMPLATE_POST_TYPE } from '../../utils/constants';
-import PageTemplates from '../page-templates';
-import Editor from '../editor';
-import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse';
-
-export const templatesListViewRoute = {
- name: 'templates-list-view',
- match: ( params ) => {
- return (
- params.isCustom !== 'true' &&
- params.layout === 'list' &&
- params.postType === TEMPLATE_POST_TYPE &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: ,
- content: ,
- mobile: ,
- preview: ,
- },
- widths: {
- content: 380,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/templates-view.js b/packages/edit-site/src/components/site-editor-routes/templates-view.js
deleted file mode 100644
index 40fd88c0e60a61..00000000000000
--- a/packages/edit-site/src/components/site-editor-routes/templates-view.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Internal dependencies
- */
-import { TEMPLATE_POST_TYPE } from '../../utils/constants';
-import PageTemplates from '../page-templates';
-import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse';
-
-export const templatesViewRoute = {
- name: 'templates-view',
- match: ( params ) => {
- return (
- ( params.isCustom === 'true' || params.layout !== 'list' ) &&
- params.postType === TEMPLATE_POST_TYPE &&
- params.canvas !== 'edit'
- );
- },
- areas: {
- sidebar: ,
- content: ,
- mobile: ,
- },
-};
diff --git a/packages/edit-site/src/components/site-editor-routes/templates.js b/packages/edit-site/src/components/site-editor-routes/templates.js
new file mode 100644
index 00000000000000..06ba07fcd06595
--- /dev/null
+++ b/packages/edit-site/src/components/site-editor-routes/templates.js
@@ -0,0 +1,45 @@
+/**
+ * WordPress dependencies
+ */
+import { privateApis as routerPrivateApis } from '@wordpress/router';
+
+/**
+ * Internal dependencies
+ */
+import Editor from '../editor';
+import SidebarNavigationScreenTemplatesBrowse from '../sidebar-navigation-screen-templates-browse';
+import { unlock } from '../../lock-unlock';
+import PageTemplates from '../page-templates';
+
+const { useLocation } = unlock( routerPrivateApis );
+
+function MobileTemplatesView() {
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
+
+ return canvas === 'edit' ? (
+
+ ) : (
+
+ );
+}
+
+export const templatesRoute = {
+ name: 'templates',
+ path: '/template',
+ areas: {
+ sidebar: ,
+ content: ,
+ preview( { query } ) {
+ const isListView = query.layout === 'list';
+ return isListView ? : undefined;
+ },
+ mobile: ,
+ },
+ widths: {
+ content( { query } ) {
+ const isListView = query.layout === 'list';
+ return isListView ? 380 : undefined;
+ },
+ },
+};
diff --git a/packages/edit-site/src/components/site-hub/index.js b/packages/edit-site/src/components/site-hub/index.js
index 9e57034bfe73aa..91324356d01975 100644
--- a/packages/edit-site/src/components/site-hub/index.js
+++ b/packages/edit-site/src/components/site-hub/index.js
@@ -39,8 +39,7 @@ const SiteHub = memo(
const { getEntityRecord } = select( coreStore );
const _site = getEntityRecord( 'root', 'site' );
return {
- dashboardLink:
- getSettings().__experimentalDashboardLink || 'index.php',
+ dashboardLink: getSettings().__experimentalDashboardLink,
homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home,
siteTitle:
! _site?.title && !! _site?.url
@@ -129,9 +128,7 @@ export const SiteHubMobile = memo(
select( coreStore );
const _site = getEntityRecord( 'root', 'site' );
return {
- dashboardLink:
- getSettings().__experimentalDashboardLink ||
- 'index.php',
+ dashboardLink: getSettings().__experimentalDashboardLink,
isBlockTheme: getCurrentTheme()?.is_block_theme,
homeUrl: getEntityRecord( 'root', '__unstableBase' )?.home,
siteTitle:
@@ -170,7 +167,7 @@ export const SiteHubMobile = memo(
}
: {
onClick: () => {
- history.push( {} );
+ history.navigate( '/' );
navigate( 'back' );
},
label: __( 'Go to Site Editor' ),
diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js
index 3e87f8721e116a..34ddae3e1af7a4 100644
--- a/packages/edit-site/src/hooks/commands/use-common-commands.js
+++ b/packages/edit-site/src/hooks/commands/use-common-commands.js
@@ -49,27 +49,17 @@ const getGlobalStylesOpenStylesCommands = () =>
label: __( 'Open styles' ),
callback: ( { close } ) => {
close();
- if ( ! params.postId ) {
- history.push( {
- path: '/wp_global_styles',
- canvas: 'edit',
+ if ( canvas !== 'edit' ) {
+ history.navigate( '/styles?canvas=edit', {
+ transition: 'canvas-mode-edit-transition',
} );
}
- if ( params.postId && canvas !== 'edit' ) {
- history.push(
- { ...params, canvas: 'edit' },
- undefined,
- {
- transition: 'canvas-mode-edit-transition',
- }
- );
- }
openGeneralSidebar( 'edit-site/global-styles' );
},
icon: styles,
},
];
- }, [ history, openGeneralSidebar, params, canvas, isBlockBasedTheme ] );
+ }, [ history, openGeneralSidebar, canvas, isBlockBasedTheme ] );
return {
isLoading: false,
@@ -100,24 +90,11 @@ const getGlobalStylesToggleWelcomeGuideCommands = () =>
label: __( 'Learn about styles' ),
callback: ( { close } ) => {
close();
- if ( ! params.postId ) {
- history.push( {
- path: '/wp_global_styles',
- canvas: 'edit',
+ if ( canvas !== 'edit' ) {
+ history.navigate( '/styles?canvas=edit', {
+ transition: 'canvas-mode-edit-transition',
} );
}
- if ( params.postId && canvas !== 'edit' ) {
- history.push(
- {
- ...params,
- canvas: 'edit',
- },
- undefined,
- {
- transition: 'canvas-mode-edit-transition',
- }
- );
- }
openGeneralSidebar( 'edit-site/global-styles' );
set( 'core/edit-site', 'welcomeGuideStyles', true );
// sometimes there's a focus loss that happens after some time
@@ -129,14 +106,7 @@ const getGlobalStylesToggleWelcomeGuideCommands = () =>
icon: help,
},
];
- }, [
- history,
- openGeneralSidebar,
- canvas,
- isBlockBasedTheme,
- set,
- params,
- ] );
+ }, [ history, openGeneralSidebar, canvas, isBlockBasedTheme, set ] );
return {
isLoading: false,
@@ -205,24 +175,11 @@ const getGlobalStylesOpenCssCommands = () =>
icon: brush,
callback: ( { close } ) => {
close();
- if ( ! params.postId ) {
- history.push( {
- path: '/wp_global_styles',
- canvas: 'edit',
+ if ( canvas !== 'edit' ) {
+ history.navigate( '/styles?canvas=edit', {
+ transition: 'canvas-mode-edit-transition',
} );
}
- if ( params.postId && canvas !== 'edit' ) {
- history.push(
- {
- ...params,
- canvas: 'edit',
- },
- undefined,
- {
- transition: 'canvas-mode-edit-transition',
- }
- );
- }
openGeneralSidebar( 'edit-site/global-styles' );
setEditorCanvasContainerView( 'global-styles-css' );
},
@@ -234,7 +191,6 @@ const getGlobalStylesOpenCssCommands = () =>
setEditorCanvasContainerView,
canEditCSS,
canvas,
- params,
] );
return {
isLoading: false,
@@ -272,24 +228,11 @@ const getGlobalStylesOpenRevisionsCommands = () =>
icon: backup,
callback: ( { close } ) => {
close();
- if ( ! params.postId ) {
- history.push( {
- path: '/wp_global_styles',
- canvas: 'edit',
+ if ( canvas !== 'edit' ) {
+ history.navigate( '/styles?canvas=edit', {
+ transition: 'canvas-mode-edit-transition',
} );
}
- if ( params.postId && canvas !== 'edit' ) {
- history.push(
- {
- ...params,
- canvas: 'edit',
- },
- undefined,
- {
- transition: 'canvas-mode-edit-transition',
- }
- );
- }
openGeneralSidebar( 'edit-site/global-styles' );
setEditorCanvasContainerView(
'global-styles-revisions'
@@ -303,7 +246,6 @@ const getGlobalStylesOpenRevisionsCommands = () =>
openGeneralSidebar,
setEditorCanvasContainerView,
canvas,
- params,
] );
return {
diff --git a/packages/edit-site/src/hooks/commands/use-set-command-context.js b/packages/edit-site/src/hooks/commands/use-set-command-context.js
index e27c4ca91582fd..6ecdf04989609b 100644
--- a/packages/edit-site/src/hooks/commands/use-set-command-context.js
+++ b/packages/edit-site/src/hooks/commands/use-set-command-context.js
@@ -19,8 +19,8 @@ const { useLocation } = unlock( routerPrivateApis );
* React hook used to set the correct command context based on the current state.
*/
export default function useSetCommandContext() {
- const { params } = useLocation();
- const { canvas = 'view' } = params;
+ const { query = {} } = useLocation();
+ const { canvas = 'view' } = query;
const hasBlockSelected = useSelect( ( select ) => {
return select( blockEditorStore ).getBlockSelectionStart();
}, [] );
diff --git a/packages/edit-site/src/store/private-actions.js b/packages/edit-site/src/store/private-actions.js
index 1db3873acedda2..9b16748049cd0e 100644
--- a/packages/edit-site/src/store/private-actions.js
+++ b/packages/edit-site/src/store/private-actions.js
@@ -18,3 +18,10 @@ export function registerRoute( route ) {
route,
};
}
+
+export function unregisterRoute( name ) {
+ return {
+ type: 'UNREGISTER_ROUTE',
+ name,
+ };
+}
diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js
index 3ce067c25c1954..7ffb276a35da10 100644
--- a/packages/edit-site/src/store/reducer.js
+++ b/packages/edit-site/src/store/reducer.js
@@ -85,6 +85,8 @@ function routes( state = [], action ) {
switch ( action.type ) {
case 'REGISTER_ROUTE':
return [ ...state, action.route ];
+ case 'UNREGISTER_ROUTE':
+ return state.filter( ( route ) => route.name !== action.name );
}
return state;
diff --git a/packages/edit-site/src/utils/is-previewing-theme.js b/packages/edit-site/src/utils/is-previewing-theme.js
index 1a71c441f9925e..a4c830b4b60ad7 100644
--- a/packages/edit-site/src/utils/is-previewing-theme.js
+++ b/packages/edit-site/src/utils/is-previewing-theme.js
@@ -4,9 +4,7 @@
import { getQueryArg } from '@wordpress/url';
export function isPreviewingTheme() {
- return (
- getQueryArg( window.location.href, 'wp_theme_preview' ) !== undefined
- );
+ return !! getQueryArg( window.location.href, 'wp_theme_preview' );
}
export function currentlyPreviewingTheme() {
diff --git a/packages/edit-site/src/utils/use-activate-theme.js b/packages/edit-site/src/utils/use-activate-theme.js
index 0dafd88340ba75..447ea073053492 100644
--- a/packages/edit-site/src/utils/use-activate-theme.js
+++ b/packages/edit-site/src/utils/use-activate-theme.js
@@ -4,6 +4,7 @@
import { store as coreStore } from '@wordpress/core-data';
import { useDispatch } from '@wordpress/data';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -14,7 +15,7 @@ import {
currentlyPreviewingTheme,
} from './is-previewing-theme';
-const { useHistory } = unlock( routerPrivateApis );
+const { useHistory, useLocation } = unlock( routerPrivateApis );
/**
* This should be refactored to use the REST API, once the REST API can activate themes.
@@ -23,6 +24,7 @@ const { useHistory } = unlock( routerPrivateApis );
*/
export function useActivateTheme() {
const history = useHistory();
+ const { path } = useLocation();
const { startResolution, finishResolution } = useDispatch( coreStore );
return async () => {
@@ -37,8 +39,7 @@ export function useActivateTheme() {
finishResolution( 'activateTheme' );
// Remove the wp_theme_preview query param: we've finished activating
// the queue and are switching to normal Site Editor.
- const { params } = history.getLocationWithParams();
- history.replace( { ...params, wp_theme_preview: undefined } );
+ history.navigate( addQueryArgs( path, { wp_theme_preview: '' } ) );
}
};
}
diff --git a/packages/router/package.json b/packages/router/package.json
index 26b4f29df04f60..66a64f4ddc5baa 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -29,10 +29,12 @@
"types": "build-types",
"dependencies": {
"@babel/runtime": "7.25.7",
+ "@wordpress/compose": "*",
"@wordpress/element": "*",
"@wordpress/private-apis": "*",
"@wordpress/url": "*",
- "history": "^5.3.0"
+ "history": "^5.3.0",
+ "route-recognizer": "^0.3.4"
},
"peerDependencies": {
"react": "^18.0.0"
diff --git a/packages/router/src/history.ts b/packages/router/src/history.ts
deleted file mode 100644
index 6cbef108eec206..00000000000000
--- a/packages/router/src/history.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * External dependencies
- */
-import { createBrowserHistory, type BrowserHistory } from 'history';
-
-/**
- * WordPress dependencies
- */
-import { buildQueryString } from '@wordpress/url';
-
-export interface EnhancedHistory extends BrowserHistory {
- getLocationWithParams: () => Location;
-}
-
-interface PushOptions {
- transition?: string;
-}
-
-const history = createBrowserHistory();
-
-const originalHistoryPush = history.push;
-const originalHistoryReplace = history.replace;
-
-// Preserve the `wp_theme_preview` query parameter when navigating
-// around the Site Editor.
-// TODO: move this hack out of the router into Site Editor code.
-function preserveThemePreview( params: Record< string, any > ) {
- if ( params.hasOwnProperty( 'wp_theme_preview' ) ) {
- return params;
- }
- const currentSearch = new URLSearchParams( history.location.search );
- const currentThemePreview = currentSearch.get( 'wp_theme_preview' );
- if ( currentThemePreview === null ) {
- return params;
- }
- return { ...params, wp_theme_preview: currentThemePreview };
-}
-
-function push(
- params: Record< string, any >,
- state: Record< string, any >,
- options: PushOptions = {}
-) {
- const performPush = () => {
- const search = buildQueryString( preserveThemePreview( params ) );
- return originalHistoryPush.call( history, { search }, state );
- };
-
- /*
- * Skip transition in mobile, otherwise it crashes the browser.
- * See: https://github.com/WordPress/gutenberg/pull/63002.
- */
- const isMediumOrBigger = window.matchMedia( '(min-width: 782px)' ).matches;
- if (
- ! isMediumOrBigger ||
- // @ts-expect-error
- ! document.startViewTransition ||
- ! options.transition
- ) {
- return performPush();
- }
- document.documentElement.classList.add( options.transition );
- // @ts-expect-error
- const transition = document.startViewTransition( () => performPush() );
- transition.finished.finally( () => {
- document.documentElement.classList.remove( options.transition ?? '' );
- } );
-}
-
-function replace(
- params: Record< string, any >,
- state: Record< string, any >
-) {
- const search = buildQueryString( preserveThemePreview( params ) );
- return originalHistoryReplace.call( history, { search }, state );
-}
-
-const locationMemo = new WeakMap();
-function getLocationWithParams() {
- const location = history.location;
- let locationWithParams = locationMemo.get( location );
- if ( ! locationWithParams ) {
- locationWithParams = {
- ...location,
- params: Object.fromEntries(
- new URLSearchParams( location.search )
- ),
- };
- locationMemo.set( location, locationWithParams );
- }
- return locationWithParams;
-}
-
-export default {
- ...history,
- push,
- replace,
- getLocationWithParams,
-};
diff --git a/packages/router/src/link.tsx b/packages/router/src/link.tsx
new file mode 100644
index 00000000000000..d312a9da144601
--- /dev/null
+++ b/packages/router/src/link.tsx
@@ -0,0 +1,55 @@
+/**
+ * WordPress dependencies
+ */
+import { useContext, useMemo } from '@wordpress/element';
+import { getQueryArgs, getPath, buildQueryString } from '@wordpress/url';
+
+/**
+ * Internal dependencies
+ */
+import { ConfigContext, type NavigationOptions, useHistory } from './router';
+
+export function useLink( to: string, options: NavigationOptions = {} ) {
+ const history = useHistory();
+ const { pathArg, beforeNavigate } = useContext( ConfigContext );
+ function onClick( event: React.SyntheticEvent< HTMLAnchorElement > ) {
+ event?.preventDefault();
+ history.navigate( to, options );
+ }
+ const query = getQueryArgs( to );
+ const path = getPath( 'http://domain.com/' + to ) ?? '';
+ const link = useMemo( () => {
+ return beforeNavigate
+ ? beforeNavigate( { path, query } )
+ : { path, query };
+ }, [ path, query, beforeNavigate ] );
+
+ const [ before ] = window.location.href.split( '?' );
+
+ return {
+ href: `${ before }?${ buildQueryString( {
+ [ pathArg ]: link.path,
+ ...link.query,
+ } ) }`,
+ onClick,
+ };
+}
+
+export function Link( {
+ to,
+ options,
+ children,
+ ...props
+}: {
+ to: string;
+ options?: NavigationOptions;
+ children: React.ReactNode;
+} ) {
+ const { href, onClick } = useLink( to, options );
+
+ return (
+
+ { children }
+
+ );
+}
diff --git a/packages/router/src/private-apis.ts b/packages/router/src/private-apis.ts
index 7b2945a24ab1a1..9ef316ed716cf4 100644
--- a/packages/router/src/private-apis.ts
+++ b/packages/router/src/private-apis.ts
@@ -2,6 +2,7 @@
* Internal dependencies
*/
import { useHistory, useLocation, RouterProvider } from './router';
+import { useLink, Link } from './link';
import { lock } from './lock-unlock';
export const privateApis = {};
@@ -9,4 +10,6 @@ lock( privateApis, {
useHistory,
useLocation,
RouterProvider,
+ useLink,
+ Link,
} );
diff --git a/packages/router/src/router.tsx b/packages/router/src/router.tsx
index 9a1d01aa5f8d88..ea0b218fa6a401 100644
--- a/packages/router/src/router.tsx
+++ b/packages/router/src/router.tsx
@@ -1,3 +1,9 @@
+/**
+ * External dependencies
+ */
+import RouteRecognizer from 'route-recognizer';
+import { createBrowserHistory } from 'history';
+
/**
* WordPress dependencies
*/
@@ -5,37 +11,227 @@ import {
createContext,
useContext,
useSyncExternalStore,
+ useMemo,
} from '@wordpress/element';
+import {
+ addQueryArgs,
+ getQueryArgs,
+ getPath,
+ buildQueryString,
+} from '@wordpress/url';
+import { useEvent } from '@wordpress/compose';
/**
* Internal dependencies
*/
-import history from './history';
-import type { EnhancedHistory } from './history';
+import type { ReactNode } from 'react';
+
+const history = createBrowserHistory();
+interface Route {
+ name: string;
+ path: string;
+ areas: Record< string, ReactNode >;
+ widths: Record< string, number >;
+}
+
+type LocationWithQuery = Location & {
+ query?: Record< string, any >;
+};
+
+interface Match {
+ name: string;
+ path: string;
+ areas: Record< string, ReactNode >;
+ widths: Record< string, number >;
+ query?: Record< string, any >;
+ params?: Record< string, any >;
+}
+
+export type BeforeNavigate = ( arg: {
+ path: string;
+ query: Record< string, any >;
+} ) => {
+ path: string;
+ query: Record< string, any >;
+};
+
+interface Config {
+ pathArg: string;
+ beforeNavigate?: BeforeNavigate;
+}
+
+export interface NavigationOptions {
+ transition?: string;
+ state?: Record< string, any >;
+}
-const RoutesContext = createContext< Location | null >( null );
-const HistoryContext = createContext< EnhancedHistory >( history );
+const RoutesContext = createContext< Match | null >( null );
+export const ConfigContext = createContext< Config >( { pathArg: 'p' } );
+
+const locationMemo = new WeakMap();
+function getLocationWithQuery() {
+ const location = history.location;
+ let locationWithQuery = locationMemo.get( location );
+ if ( ! locationWithQuery ) {
+ locationWithQuery = {
+ ...location,
+ query: Object.fromEntries( new URLSearchParams( location.search ) ),
+ };
+ locationMemo.set( location, locationWithQuery );
+ }
+ return locationWithQuery;
+}
export function useLocation() {
- return useContext( RoutesContext );
+ const context = useContext( RoutesContext );
+ if ( ! context ) {
+ throw new Error( 'useLocation must be used within a RouterProvider' );
+ }
+ return context;
}
export function useHistory() {
- return useContext( HistoryContext );
+ const { pathArg, beforeNavigate } = useContext( ConfigContext );
+
+ const navigate = useEvent(
+ async ( rawPath: string, options: NavigationOptions = {} ) => {
+ const query = getQueryArgs( rawPath );
+ const path = getPath( 'http://domain.com/' + rawPath ) ?? '';
+ const performPush = () => {
+ const result = beforeNavigate
+ ? beforeNavigate( { path, query } )
+ : { path, query };
+ return history.push(
+ {
+ search: buildQueryString( {
+ [ pathArg ]: result.path,
+ ...result.query,
+ } ),
+ },
+ options.state
+ );
+ };
+
+ /*
+ * Skip transition in mobile, otherwise it crashes the browser.
+ * See: https://github.com/WordPress/gutenberg/pull/63002.
+ */
+ const isMediumOrBigger =
+ window.matchMedia( '(min-width: 782px)' ).matches;
+ if (
+ ! isMediumOrBigger ||
+ // @ts-expect-error
+ ! document.startViewTransition ||
+ ! options.transition
+ ) {
+ performPush();
+ }
+
+ await new Promise< void >( ( resolve ) => {
+ const classname = options.transition ?? '';
+ document.documentElement.classList.add( classname );
+ // @ts-expect-error
+ const transition = document.startViewTransition( () =>
+ performPush()
+ );
+ transition.finished.finally( () => {
+ document.documentElement.classList.remove( classname );
+ resolve();
+ } );
+ } );
+ }
+ );
+
+ return useMemo(
+ () => ( {
+ navigate,
+ } ),
+ [ navigate ]
+ );
+}
+
+export default function useMatch(
+ location: LocationWithQuery,
+ matcher: RouteRecognizer,
+ pathArg: string
+): Match {
+ const { query: rawQuery = {} } = location;
+
+ return useMemo( () => {
+ const { [ pathArg ]: path = '/', ...query } = rawQuery;
+ const result = matcher.recognize( path )?.[ 0 ];
+ if ( ! result ) {
+ return {
+ name: '404',
+ path: addQueryArgs( path, query ),
+ areas: {},
+ widths: {},
+ query,
+ params: {},
+ };
+ }
+
+ const matchedRoute = result.handler as Route;
+ const resolveFunctions = ( record: Record< string, any > = {} ) => {
+ return Object.fromEntries(
+ Object.entries( record ).map( ( [ key, value ] ) => {
+ if ( typeof value === 'function' ) {
+ return [
+ key,
+ value( { query, params: result.params } ),
+ ];
+ }
+ return [ key, value ];
+ } )
+ );
+ };
+ return {
+ name: matchedRoute.name,
+ areas: resolveFunctions( matchedRoute.areas ),
+ widths: resolveFunctions( matchedRoute.widths ),
+ params: result.params,
+ query,
+ path: addQueryArgs( path, query ),
+ };
+ }, [ matcher, rawQuery, pathArg ] );
}
-export function RouterProvider( { children }: { children: React.ReactNode } ) {
+export function RouterProvider( {
+ routes,
+ pathArg,
+ beforeNavigate,
+ children,
+}: {
+ routes: Route[];
+ pathArg: string;
+ beforeNavigate?: BeforeNavigate;
+ children: React.ReactNode;
+} ) {
const location = useSyncExternalStore(
history.listen,
- history.getLocationWithParams,
- history.getLocationWithParams
+ getLocationWithQuery,
+ getLocationWithQuery
+ );
+ const matcher = useMemo( () => {
+ const ret = new RouteRecognizer();
+ routes.forEach( ( route ) => {
+ ret.add( [ { path: route.path, handler: route } ], {
+ as: route.name,
+ } );
+ } );
+ return ret;
+ }, [ routes ] );
+ const match = useMatch( location, matcher, pathArg );
+ const config = useMemo(
+ () => ( { beforeNavigate, pathArg } ),
+ [ beforeNavigate, pathArg ]
);
return (
-
-
+
+
{ children }
-
+
);
}
diff --git a/packages/router/tsconfig.json b/packages/router/tsconfig.json
index e4945eef8bac0c..8706b546ff304d 100644
--- a/packages/router/tsconfig.json
+++ b/packages/router/tsconfig.json
@@ -4,11 +4,10 @@
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types",
- "types": [ "gutenberg-env" ],
- "allowJs": false,
- "checkJs": false
+ "types": [ "gutenberg-env" ]
},
"references": [
+ { "path": "../compose" },
{ "path": "../element" },
{ "path": "../private-apis" },
{ "path": "../url" }
diff --git a/test/e2e/specs/editor/various/pattern-overrides.spec.js b/test/e2e/specs/editor/various/pattern-overrides.spec.js
index 20eff4096cb1cc..7069b4cec258ab 100644
--- a/test/e2e/specs/editor/various/pattern-overrides.spec.js
+++ b/test/e2e/specs/editor/various/pattern-overrides.spec.js
@@ -128,7 +128,11 @@ test.describe( 'Pattern Overrides', () => {
page.getByRole( 'button', { name: 'Dismiss this notice' } )
).toBeVisible();
- patternId = new URL( page.url() ).searchParams.get( 'postId' );
+ patternId = await page.evaluate( () => {
+ return window.wp.data
+ .select( 'core/editor' )
+ .getCurrentPostId();
+ } );
} );
await test.step( 'Create a post and insert the pattern with overrides', async () => {
@@ -1207,7 +1211,11 @@ test.describe( 'Pattern Overrides', () => {
page.getByRole( 'button', { name: 'Dismiss this notice' } )
).toBeVisible();
- patternId = new URL( page.url() ).searchParams.get( 'postId' );
+ patternId = await page.evaluate( () => {
+ return window.wp.data
+ .select( 'core/editor' )
+ .getCurrentPostId();
+ } );
} );
await test.step( 'create a post and insert the pattern with synced values', async () => {
diff --git a/test/e2e/specs/site-editor/browser-history.spec.js b/test/e2e/specs/site-editor/browser-history.spec.js
index eaafb3aad1b3fd..a2326d10e3cc51 100644
--- a/test/e2e/specs/site-editor/browser-history.spec.js
+++ b/test/e2e/specs/site-editor/browser-history.spec.js
@@ -21,13 +21,13 @@ test.describe( 'Site editor browser history', () => {
await page.click( 'role=button[name="Templates"]' );
await page.getByRole( 'link', { name: 'Index' } ).click();
await expect( page ).toHaveURL(
- '/wp-admin/site-editor.php?postId=emptytheme%2F%2Findex&postType=wp_template&canvas=edit'
+ '/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Findex&canvas=edit'
);
// Navigate back to the template list
await page.goBack();
await expect( page ).toHaveURL(
- '/wp-admin/site-editor.php?postType=wp_template'
+ '/wp-admin/site-editor.php?p=%2Ftemplate'
);
// Navigate back to the dashboard
diff --git a/test/e2e/specs/site-editor/command-center.spec.js b/test/e2e/specs/site-editor/command-center.spec.js
index 19318081aa171b..197a01c43c8b46 100644
--- a/test/e2e/specs/site-editor/command-center.spec.js
+++ b/test/e2e/specs/site-editor/command-center.spec.js
@@ -28,7 +28,7 @@ test.describe( 'Site editor command palette', () => {
await page.keyboard.type( 'new page' );
await page.getByRole( 'option', { name: 'Add new page' } ).click();
await expect( page ).toHaveURL(
- /\/wp-admin\/site-editor.php\?postId=(\d+)&postType=page&canvas=edit/
+ /\/wp-admin\/site-editor.php\?p=%2Fpage%2F(\d+)&canvas=edit/
);
await expect(
editor.canvas
diff --git a/test/e2e/specs/site-editor/hybrid-theme.spec.js b/test/e2e/specs/site-editor/hybrid-theme.spec.js
index b568aaf4445b5c..042cb1042cac22 100644
--- a/test/e2e/specs/site-editor/hybrid-theme.spec.js
+++ b/test/e2e/specs/site-editor/hybrid-theme.spec.js
@@ -33,7 +33,7 @@ test.describe( 'Hybrid theme', () => {
);
await expect( page ).toHaveURL(
- '/wp-admin/site-editor.php?postType=wp_template_part'
+ '/wp-admin/site-editor.php?p=%2Fpattern&postType=wp_template_part'
);
await expect(
diff --git a/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js b/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js
index f26fb8e13b8c3c..a0cc0af5463aed 100644
--- a/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js
+++ b/test/e2e/specs/site-editor/site-editor-url-navigation.spec.js
@@ -44,7 +44,7 @@ test.describe( 'Site editor url navigation', () => {
.click();
await page.getByRole( 'option', { name: 'Demo' } ).click();
await expect( page ).toHaveURL(
- '/wp-admin/site-editor.php?postId=emptytheme%2F%2Fsingle-post-demo&postType=wp_template&canvas=edit'
+ '/wp-admin/site-editor.php?p=%2Fwp_template%2Femptytheme%2F%2Fsingle-post-demo&canvas=edit'
);
} );
@@ -63,7 +63,7 @@ test.describe( 'Site editor url navigation', () => {
await page.type( 'role=dialog >> role=textbox[name="Name"i]', 'Demo' );
await page.keyboard.press( 'Enter' );
await expect( page ).toHaveURL(
- '/wp-admin/site-editor.php?postId=emptytheme%2F%2Fdemo&postType=wp_template_part&canvas=edit'
+ '/wp-admin/site-editor.php?p=%2Fwp_template_part%2Femptytheme%2F%2Fdemo&canvas=edit'
);
} );