diff --git a/docs/manifest.json b/docs/manifest.json
index 454b67562bfac..304acd00a79ea 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -1493,6 +1493,12 @@
"markdown_source": "../packages/compose/README.md",
"parent": "packages"
},
+ {
+ "title": "@wordpress/core-commands",
+ "slug": "packages-core-commands",
+ "markdown_source": "../packages/core-commands/README.md",
+ "parent": "packages"
+ },
{
"title": "@wordpress/core-data",
"slug": "packages-core-data",
diff --git a/package-lock.json b/package-lock.json
index b2b47d2a18aeb..56a0039352cb6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17086,6 +17086,21 @@
"use-memo-one": "^1.1.1"
}
},
+ "@wordpress/core-commands": {
+ "version": "file:packages/core-commands",
+ "requires": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/commands": "file:packages/commands",
+ "@wordpress/core-data": "file:packages/core-data",
+ "@wordpress/data": "file:packages/data",
+ "@wordpress/element": "file:packages/element",
+ "@wordpress/i18n": "file:packages/i18n",
+ "@wordpress/icons": "file:packages/icons",
+ "@wordpress/private-apis": "file:packages/private-apis",
+ "@wordpress/router": "file:packages/router",
+ "@wordpress/url": "file:packages/url"
+ }
+ },
"@wordpress/core-data": {
"version": "file:packages/core-data",
"requires": {
@@ -17367,6 +17382,7 @@
"@wordpress/commands": "file:packages/commands",
"@wordpress/components": "file:packages/components",
"@wordpress/compose": "file:packages/compose",
+ "@wordpress/core-commands": "file:packages/core-commands",
"@wordpress/core-data": "file:packages/core-data",
"@wordpress/data": "file:packages/data",
"@wordpress/deprecated": "file:packages/deprecated",
diff --git a/package.json b/package.json
index c9da0d72dda1c..45b1e5ef319d2 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"@wordpress/commands": "file:packages/commands",
"@wordpress/components": "file:packages/components",
"@wordpress/compose": "file:packages/compose",
+ "@wordpress/core-commands": "file:packages/core-commands",
"@wordpress/core-data": "file:packages/core-data",
"@wordpress/customize-widgets": "file:packages/customize-widgets",
"@wordpress/data": "file:packages/data",
diff --git a/packages/core-commands/.npmrc b/packages/core-commands/.npmrc
new file mode 100644
index 0000000000000..43c97e719a5a8
--- /dev/null
+++ b/packages/core-commands/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/packages/core-commands/CHANGELOG.md b/packages/core-commands/CHANGELOG.md
new file mode 100644
index 0000000000000..6349399989da3
--- /dev/null
+++ b/packages/core-commands/CHANGELOG.md
@@ -0,0 +1,5 @@
+
+
+## Unreleased
+
+Initial release.
\ No newline at end of file
diff --git a/packages/core-commands/README.md b/packages/core-commands/README.md
new file mode 100644
index 0000000000000..a7f8073c1f1de
--- /dev/null
+++ b/packages/core-commands/README.md
@@ -0,0 +1,31 @@
+# Core Commands
+
+This package includes a list of reusable WordPress Admin commands. These commands can be used in multiple WP Admin pages.
+
+## Installation
+
+Install the module
+
+```bash
+npm install @wordpress/core-commands --save
+```
+
+_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
+
+## API
+
+
+
+### privateApis
+
+Undocumented declaration.
+
+
+
+## Contributing to this package
+
+This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
+
+To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md).
+
+
diff --git a/packages/core-commands/package.json b/packages/core-commands/package.json
new file mode 100644
index 0000000000000..8bb52848b7916
--- /dev/null
+++ b/packages/core-commands/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "@wordpress/core-commands",
+ "version": "0.1.0",
+ "description": "WordPress core reusable commands.",
+ "author": "The WordPress Contributors",
+ "license": "GPL-2.0-or-later",
+ "keywords": [
+ "wordpress",
+ "gutenberg",
+ "commands"
+ ],
+ "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/core-commands/README.md",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/WordPress/gutenberg.git",
+ "directory": "packages/core-commands"
+ },
+ "bugs": {
+ "url": "https://github.com/WordPress/gutenberg/issues"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "main": "build/index.js",
+ "module": "build-module/index.js",
+ "react-native": "src/index",
+ "sideEffects": false,
+ "dependencies": {
+ "@babel/runtime": "^7.16.0",
+ "@wordpress/commands": "file:../commands",
+ "@wordpress/core-data": "file:../core-data",
+ "@wordpress/data": "file:../data",
+ "@wordpress/element": "file:../element",
+ "@wordpress/i18n": "file:../i18n",
+ "@wordpress/icons": "file:../icons",
+ "@wordpress/private-apis": "file:../private-apis",
+ "@wordpress/router": "file:../router",
+ "@wordpress/url": "file:../url"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/edit-site/src/hooks/commands/use-wp-admin-commands.js b/packages/core-commands/src/add-post-type-commands.js
similarity index 70%
rename from packages/edit-site/src/hooks/commands/use-wp-admin-commands.js
rename to packages/core-commands/src/add-post-type-commands.js
index 81337b85684ea..516686dea0394 100644
--- a/packages/edit-site/src/hooks/commands/use-wp-admin-commands.js
+++ b/packages/core-commands/src/add-post-type-commands.js
@@ -3,7 +3,6 @@
*/
import { privateApis } from '@wordpress/commands';
import { __, sprintf } from '@wordpress/i18n';
-import { useSelect } from '@wordpress/data';
import { addQueryArgs } from '@wordpress/url';
import { useMemo } from '@wordpress/element';
import { plus } from '@wordpress/icons';
@@ -11,12 +10,11 @@ import { plus } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import { store as editSiteStore } from '../../store';
-import { unlock } from '../../private-apis';
+import { unlock } from './lock-unlock';
const { useCommandLoader } = unlock( privateApis );
-const getWPAdminAddCommandLoader = ( postType ) =>
+const getAddPostTypeCommandLoader = ( postType ) =>
function useAddCommandLoader( { search } ) {
let label;
if ( postType === 'post' ) {
@@ -36,11 +34,6 @@ const getWPAdminAddCommandLoader = ( postType ) =>
label = sprintf( __( 'Add a new page "%s"' ), search );
}
- const newPostLink = useSelect( ( select ) => {
- const { getSettings } = unlock( select( editSiteStore ) );
- return getSettings().newPostLink ?? 'post-new.php';
- }, [] );
-
const commands = useMemo(
() => [
{
@@ -48,14 +41,14 @@ const getWPAdminAddCommandLoader = ( postType ) =>
label,
icon: plus,
callback: () => {
- document.location.href = addQueryArgs( newPostLink, {
+ document.location.href = addQueryArgs( 'post-new.php', {
post_type: postType,
post_title: hasRecordTitle ? search : undefined,
} );
},
},
],
- [ newPostLink, hasRecordTitle, search, label ]
+ [ hasRecordTitle, search, label ]
);
return {
@@ -64,10 +57,10 @@ const getWPAdminAddCommandLoader = ( postType ) =>
};
};
-const useAddPostLoader = getWPAdminAddCommandLoader( 'post' );
-const useAddPageLoader = getWPAdminAddCommandLoader( 'page' );
+const useAddPostLoader = getAddPostTypeCommandLoader( 'post' );
+const useAddPageLoader = getAddPostTypeCommandLoader( 'page' );
-export function useWPAdminCommands() {
+export function useAddPostTypeCommands() {
useCommandLoader( {
name: 'core/wp-admin/add-post-loader',
hook: useAddPostLoader,
diff --git a/packages/core-commands/src/index.js b/packages/core-commands/src/index.js
new file mode 100644
index 0000000000000..94878a556278a
--- /dev/null
+++ b/packages/core-commands/src/index.js
@@ -0,0 +1 @@
+export { privateApis } from './private-apis';
diff --git a/packages/core-commands/src/lock-unlock.js b/packages/core-commands/src/lock-unlock.js
new file mode 100644
index 0000000000000..24973274f1897
--- /dev/null
+++ b/packages/core-commands/src/lock-unlock.js
@@ -0,0 +1,10 @@
+/**
+ * WordPress dependencies
+ */
+import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';
+
+export const { lock, unlock } =
+ __dangerousOptInToUnstableAPIsOnlyForCoreModules(
+ 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
+ '@wordpress/core-commands'
+ );
diff --git a/packages/core-commands/src/private-apis.js b/packages/core-commands/src/private-apis.js
new file mode 100644
index 0000000000000..b0e0cd87040f6
--- /dev/null
+++ b/packages/core-commands/src/private-apis.js
@@ -0,0 +1,16 @@
+/**
+ * Internal dependencies
+ */
+import { useAddPostTypeCommands } from './add-post-type-commands';
+import { useSiteEditorNavigationCommands } from './site-editor-navigation-commands';
+import { lock } from './lock-unlock';
+
+function useCommands() {
+ useAddPostTypeCommands();
+ useSiteEditorNavigationCommands();
+}
+
+export const privateApis = {};
+lock( privateApis, {
+ useCommands,
+} );
diff --git a/packages/edit-site/src/hooks/commands/use-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js
similarity index 75%
rename from packages/edit-site/src/hooks/commands/use-navigation-commands.js
rename to packages/core-commands/src/site-editor-navigation-commands.js
index 4620927779b44..f6524e3ba0211 100644
--- a/packages/edit-site/src/hooks/commands/use-navigation-commands.js
+++ b/packages/core-commands/src/site-editor-navigation-commands.js
@@ -8,12 +8,12 @@ import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { post, page, layout, symbolFilled } from '@wordpress/icons';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { getQueryArg, addQueryArgs, getPath } from '@wordpress/url';
/**
* Internal dependencies
*/
-import { store as editSiteStore } from '../../store';
-import { unlock } from '../../private-apis';
+import { unlock } from './lock-unlock';
const { useCommandLoader } = unlock( privateApis );
const { useHistory } = unlock( routerPrivateApis );
@@ -27,12 +27,12 @@ const icons = {
const getNavigationCommandLoaderPerPostType = ( postType ) =>
function useNavigationCommandLoader( { search } ) {
+ const history = useHistory();
const supportsSearch = ! [ 'wp_template', 'wp_template_part' ].includes(
postType
);
const deps = supportsSearch ? [ search ] : [];
- const history = useHistory();
- const { canvasMode, records, isLoading } = useSelect( ( select ) => {
+ const { records, isLoading } = useSelect( ( select ) => {
const { getEntityRecords } = select( coreStore );
const query = supportsSearch
? {
@@ -49,12 +49,20 @@ const getNavigationCommandLoaderPerPostType = ( postType ) =>
'getEntityRecords',
[ 'postType', postType, query ]
),
- canvasMode: unlock( select( editSiteStore ) ).getCanvasMode(),
+ // We're using the string literal to check whether we're in the site editor.
+ /* eslint-disable-next-line @wordpress/data-no-store-string-literals */
+ isSiteEditor: !! select( 'edit-site' ),
};
}, deps );
const commands = useMemo( () => {
return ( records ?? [] ).slice( 0, 10 ).map( ( record ) => {
+ const isSiteEditor = getPath( window.location.href )?.includes(
+ 'site-editor.php'
+ );
+ const extraArgs = isSiteEditor
+ ? { canvas: getQueryArg( window.location.href, 'canvas' ) }
+ : {};
return {
name: record.title?.rendered + ' ' + record.id,
label: record.title?.rendered
@@ -62,17 +70,25 @@ const getNavigationCommandLoaderPerPostType = ( postType ) =>
: __( '(no title)' ),
icon: icons[ postType ],
callback: ( { close } ) => {
- history.push( {
+ const args = {
postType,
postId: record.id,
- canvas:
- canvasMode === 'edit' ? canvasMode : undefined,
- } );
+ ...extraArgs,
+ };
+ const targetUrl = addQueryArgs(
+ 'site-editor.php',
+ args
+ );
+ if ( isSiteEditor ) {
+ history.push( args );
+ } else {
+ document.location = targetUrl;
+ }
close();
},
};
} );
- }, [ records, history, canvasMode ] );
+ }, [ records, history ] );
return {
commands,
@@ -89,7 +105,7 @@ const useTemplateNavigationCommandLoader =
const useTemplatePartNavigationCommandLoader =
getNavigationCommandLoaderPerPostType( 'wp_template_part' );
-export function useNavigationCommands() {
+export function useSiteEditorNavigationCommands() {
useCommandLoader( {
name: 'core/edit-site/navigate-pages',
group: __( 'Pages' ),
diff --git a/packages/edit-site/package.json b/packages/edit-site/package.json
index abe7e31e50942..ba3586301830c 100644
--- a/packages/edit-site/package.json
+++ b/packages/edit-site/package.json
@@ -35,6 +35,7 @@
"@wordpress/commands": "file:../commands",
"@wordpress/components": "file:../components",
"@wordpress/compose": "file:../compose",
+ "@wordpress/core-commands": "file:../core-commands",
"@wordpress/core-data": "file:../core-data",
"@wordpress/data": "file:../data",
"@wordpress/deprecated": "file:../deprecated",
diff --git a/packages/edit-site/src/components/layout/index.js b/packages/edit-site/src/components/layout/index.js
index 41d44040e2c3d..abc33201d6c0a 100644
--- a/packages/edit-site/src/components/layout/index.js
+++ b/packages/edit-site/src/components/layout/index.js
@@ -25,6 +25,7 @@ import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
import { CommandMenu } from '@wordpress/commands';
import { store as preferencesStore } from '@wordpress/preferences';
import { privateApis as routerPrivateApis } from '@wordpress/router';
+import { privateApis as coreCmmandsPrivateApis } from '@wordpress/core-commands';
/**
* Internal dependencies
@@ -44,7 +45,8 @@ import { unlock } from '../../private-apis';
import SavePanel from '../save-panel';
import KeyboardShortcutsRegister from '../keyboard-shortcuts/register';
import KeyboardShortcutsGlobal from '../keyboard-shortcuts/global';
-import { useCommands } from '../../hooks/commands';
+
+const { useCommands } = unlock( coreCmmandsPrivateApis );
const { useLocation } = unlock( routerPrivateApis );
diff --git a/packages/edit-site/src/hooks/commands/index.js b/packages/edit-site/src/hooks/commands/index.js
deleted file mode 100644
index 3396f12232b8d..0000000000000
--- a/packages/edit-site/src/hooks/commands/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Internal dependencies
- */
-import { useNavigationCommands } from './use-navigation-commands';
-import { useWPAdminCommands } from './use-wp-admin-commands';
-
-export function useCommands() {
- useWPAdminCommands();
- useNavigationCommands();
-}
diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js
index cf03886d76ee6..c12b431c4ceef 100644
--- a/packages/private-apis/src/implementation.js
+++ b/packages/private-apis/src/implementation.js
@@ -15,6 +15,7 @@ const CORE_MODULES_USING_PRIVATE_APIS = [
'@wordpress/blocks',
'@wordpress/commands',
'@wordpress/components',
+ '@wordpress/core-commands',
'@wordpress/customize-widgets',
'@wordpress/data',
'@wordpress/edit-post',