diff --git a/.eslintrc.js b/.eslintrc.js
index 7c89b96e997f6..adb816d615f63 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -189,11 +189,6 @@ const restrictedImports = [
message:
"edit-widgets is a WordPress top level package that shouldn't be imported into other packages",
},
- {
- name: '@wordpress/edit-navigation',
- message:
- "edit-navigation is a WordPress top level package that shouldn't be imported into other packages",
- },
];
module.exports = {
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index ebddac0375d4d..aa19138a958f1 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -50,9 +50,6 @@
/packages/customize-widgets @noisysocks
/packages/widgets @noisysocks
-# Navigation
-/packages/edit-navigation @draganescu @talldan @tellthemachines @adamziel @kevin940726 @getdave
-
# Full Site Editing
/packages/edit-site
diff --git a/bin/plugin/commands/test/__snapshots__/changelog.js.snap b/bin/plugin/commands/test/__snapshots__/changelog.js.snap
index ccdbb8e712cd1..d0af344550c04 100644
--- a/bin/plugin/commands/test/__snapshots__/changelog.js.snap
+++ b/bin/plugin/commands/test/__snapshots__/changelog.js.snap
@@ -43,6 +43,7 @@ exports[`getChangelog verify that the changelog is properly formatted 1`] = `
- Fix block appender position in classic themes. ([33895](https://github.com/WordPress/gutenberg/pull/33895))
- Fix misspelling of \\"queries\\" in filter documentation. ([33799](https://github.com/WordPress/gutenberg/pull/33799))
- Fix positioning discrepancy with draggable chip. ([33893](https://github.com/WordPress/gutenberg/pull/33893))
+- Navigation Editor: Avoid React warning when creating a new menu. ([33843](https://github.com/WordPress/gutenberg/pull/33843))
#### Block Library
- Fix justification for button block when selected. ([33739](https://github.com/WordPress/gutenberg/pull/33739))
@@ -71,10 +72,6 @@ exports[`getChangelog verify that the changelog is properly formatted 1`] = `
#### CSS & Styling
- Fix navigation block placeholder preview markup. ([33963](https://github.com/WordPress/gutenberg/pull/33963))
-#### Navigation Screen
-- Fix regressed menu selection dropdown placeholder value for Nav Editor menu locations UI. ([33748](https://github.com/WordPress/gutenberg/pull/33748))
-- Navigation Editor: Avoid React warning when creating a new menu. ([33843](https://github.com/WordPress/gutenberg/pull/33843))
-
#### Site Editor
- Fix the site editor breaking in firefox. ([33896](https://github.com/WordPress/gutenberg/pull/33896))
@@ -87,6 +84,9 @@ exports[`getChangelog verify that the changelog is properly formatted 1`] = `
#### Build Tooling
- Readable JS assets Plugin: Fix webpack 5 support. ([33785](https://github.com/WordPress/gutenberg/pull/33785))
+#### Navigation Screen
+- Fix regressed menu selection dropdown placeholder value for Nav Editor menu locations UI. ([33748](https://github.com/WordPress/gutenberg/pull/33748))
+
#### Accessibility
- Fix some JAWS bugs. ([33627](https://github.com/WordPress/gutenberg/pull/33627))
diff --git a/bin/plugin/commands/test/fixtures/pull-requests.json b/bin/plugin/commands/test/fixtures/pull-requests.json
index bb9a66a6e8e94..34f3c06c5d854 100644
--- a/bin/plugin/commands/test/fixtures/pull-requests.json
+++ b/bin/plugin/commands/test/fixtures/pull-requests.json
@@ -5099,24 +5099,6 @@
"color": "d93f0b",
"default": false,
"description": "An existing feature is broken."
- },
- {
- "id": 2074073931,
- "node_id": "MDU6TGFiZWwyMDc0MDczOTMx",
- "url": "https://api.github.com/repos/WordPress/gutenberg/labels/[Feature]%20Navigation%20Screen",
- "name": "[Feature] Navigation Screen",
- "color": "fbca04",
- "default": false,
- "description": "A new block-based screen intended to replace nav-menus.php."
- },
- {
- "id": 2536082965,
- "node_id": "MDU6TGFiZWwyNTM2MDgyOTY1",
- "url": "https://api.github.com/repos/WordPress/gutenberg/labels/[Package]%20Edit%20Navigation",
- "name": "[Package] Edit Navigation",
- "color": "ed2572",
- "default": false,
- "description": "/packages/edit-navigation"
}
],
"state": "closed",
@@ -8617,15 +8599,6 @@
"color": "fbca04",
"default": false,
"description": "A new block-based screen intended to replace nav-menus.php."
- },
- {
- "id": 2536082965,
- "node_id": "MDU6TGFiZWwyNTM2MDgyOTY1",
- "url": "https://api.github.com/repos/WordPress/gutenberg/labels/[Package]%20Edit%20Navigation",
- "name": "[Package] Edit Navigation",
- "color": "ed2572",
- "default": false,
- "description": "/packages/edit-navigation"
}
],
"state": "closed",
diff --git a/lib/client-assets.php b/lib/client-assets.php
index e23e1c4b89bd7..0f6e64c27c014 100644
--- a/lib/client-assets.php
+++ b/lib/client-assets.php
@@ -385,15 +385,6 @@ function gutenberg_register_packages_styles( $styles ) {
);
$styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' );
- gutenberg_override_style(
- $styles,
- 'wp-edit-navigation',
- gutenberg_url( 'build/edit-navigation/style.css' ),
- array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks' ),
- $version
- );
- $styles->add_data( 'wp-edit-navigation', 'rtl', 'replace' );
-
gutenberg_override_style(
$styles,
'wp-edit-site',
diff --git a/lib/experimental/navigation-page.php b/lib/experimental/navigation-page.php
deleted file mode 100644
index 77949d76aee53..0000000000000
--- a/lib/experimental/navigation-page.php
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-
- $results_per_page,
- 'context' => 'edit',
- '_locale' => 'user',
- )
- );
-}
-
-/**
- * This function returns an url for the /wp/v2/menu-items endpoint
- *
- * @since 11.8.0
- *
- * @param int $menu_id Menu ID.
- * @param int $results_per_page Results per page.
- * @return string
- */
-function gutenberg_navigation_get_menu_items_endpoint( $menu_id, $results_per_page = 100 ) {
- return '/wp/v2/menu-items?' . build_query(
- array(
- 'context' => 'edit',
- 'menus' => $menu_id,
- 'per_page' => $results_per_page,
- '_locale' => 'user',
- )
- );
-}
-
-/**
- * This function returns an url for the /wp/v2/types endpoint
- *
- * @since 11.8.0
- *
- * @return string
- */
-function gutenberg_navigation_get_types_endpoint() {
- return '/wp/v2/types?' . build_query(
- array(
- 'context' => 'edit',
- )
- );
-}
-
-/**
- * Initialize the Gutenberg Navigation page.
- *
- * @param string $hook Page.
- * @since 7.8.0
- */
-function gutenberg_navigation_init( $hook ) {
- if ( 'gutenberg_page_gutenberg-navigation' !== $hook ) {
- return;
- }
-
- $menus = wp_get_nav_menus();
- $first_menu_id = ! empty( $menus ) ? $menus[0]->term_id : null;
-
- $preload_paths = array(
- '/wp/v2/menu-locations',
- array( '/wp/v2/pages', 'OPTIONS' ),
- array( '/wp/v2/posts', 'OPTIONS' ),
- gutenberg_navigation_get_types_endpoint(),
- );
-
- if ( $first_menu_id ) {
- $preload_paths[] = gutenberg_navigation_get_menu_items_endpoint( $first_menu_id );
- }
-
- $custom_settings = array(
- 'blockNavMenus' => false,
- // We should uncomment the line below when the block-nav-menus feature becomes stable.
- // @see https://github.com/WordPress/gutenberg/issues/34265.
- /*'blockNavMenus' => get_theme_support( 'block-nav-menus' ),*/
- );
-
- $context = new WP_Block_Editor_Context( array( 'name' => 'core/edit-navigation' ) );
- $settings = get_block_editor_settings( $custom_settings, $context );
- gutenberg_initialize_editor(
- 'navigation_editor',
- 'edit-navigation',
- array(
- 'initializer_name' => 'initialize',
- 'editor_settings' => $settings,
- 'preload_paths' => $preload_paths,
- )
- );
-
- gutenberg_navigation_editor_preload_menus();
-
- wp_enqueue_script( 'wp-edit-navigation' );
- wp_enqueue_style( 'wp-edit-navigation' );
- wp_enqueue_script( 'wp-format-library' );
- wp_enqueue_style( 'wp-format-library' );
- do_action( 'enqueue_block_editor_assets' );
-}
-add_action( 'admin_enqueue_scripts', 'gutenberg_navigation_init' );
-
-/**
- * Tells the script loader to load the scripts and styles of custom block on navigation editor screen.
- *
- * @param bool $is_block_editor_screen Current decision about loading block assets.
- * @return bool Filtered decision about loading block assets.
- */
-function gutenberg_navigation_editor_load_block_editor_scripts_and_styles( $is_block_editor_screen ) {
- if ( is_callable( 'get_current_screen' ) && get_current_screen() && 'gutenberg_page_gutenberg-navigation' === get_current_screen()->base ) {
- return true;
- }
-
- return $is_block_editor_screen;
-}
-
-add_filter( 'should_load_block_editor_scripts_and_styles', 'gutenberg_navigation_editor_load_block_editor_scripts_and_styles' );
-
-/**
- * This function calls createMenuPreloadingMiddleware middleware because
- * we need to use custom preloading logic for menus.
- *
- * @return void
- */
-function gutenberg_navigation_editor_preload_menus() {
- $menus_data = array_reduce(
- array(
- gutenberg_navigation_get_menus_endpoint(),
- ),
- 'rest_preload_api_request',
- array()
- );
-
- if ( ! $menus_data ) {
- return;
- }
-
- wp_add_inline_script(
- 'wp-edit-navigation',
- sprintf(
- 'wp.apiFetch.use( wp.editNavigation.__unstableCreateMenuPreloadingMiddleware( %s ) );',
- wp_json_encode( $menus_data )
- ),
- 'after'
- );
-}
diff --git a/lib/load.php b/lib/load.php
index 71e48264a73f3..9467312a7b955 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -94,7 +94,6 @@ function gutenberg_is_experiment_enabled( $name ) {
}
require __DIR__ . '/experimental/blocks.php';
require __DIR__ . '/experimental/navigation-theme-opt-in.php';
-require __DIR__ . '/experimental/navigation-page.php';
require __DIR__ . '/experimental/kses.php';
// Fonts API.
diff --git a/package-lock.json b/package-lock.json
index 75f24270366df..25ee3155936ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17705,35 +17705,6 @@
"uuid": "^8.3.0"
}
},
- "@wordpress/edit-navigation": {
- "version": "file:packages/edit-navigation",
- "requires": {
- "@babel/runtime": "^7.16.0",
- "@wordpress/api-fetch": "file:packages/api-fetch",
- "@wordpress/block-editor": "file:packages/block-editor",
- "@wordpress/block-library": "file:packages/block-library",
- "@wordpress/blocks": "file:packages/blocks",
- "@wordpress/components": "file:packages/components",
- "@wordpress/compose": "file:packages/compose",
- "@wordpress/core-data": "file:packages/core-data",
- "@wordpress/data": "file:packages/data",
- "@wordpress/dom": "file:packages/dom",
- "@wordpress/element": "file:packages/element",
- "@wordpress/hooks": "file:packages/hooks",
- "@wordpress/html-entities": "file:packages/html-entities",
- "@wordpress/i18n": "file:packages/i18n",
- "@wordpress/icons": "file:packages/icons",
- "@wordpress/interface": "file:packages/interface",
- "@wordpress/keyboard-shortcuts": "file:packages/keyboard-shortcuts",
- "@wordpress/keycodes": "file:packages/keycodes",
- "@wordpress/notices": "file:packages/notices",
- "@wordpress/plugins": "file:packages/plugins",
- "@wordpress/preferences": "file:packages/preferences",
- "@wordpress/url": "file:packages/url",
- "classnames": "^2.3.1",
- "lodash": "^4.17.21"
- }
- },
"@wordpress/edit-post": {
"version": "file:packages/edit-post",
"requires": {
diff --git a/package.json b/package.json
index b8aa12b89fb0e..137a0e3b4b8bc 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,6 @@
"@wordpress/deprecated": "file:packages/deprecated",
"@wordpress/dom": "file:packages/dom",
"@wordpress/dom-ready": "file:packages/dom-ready",
- "@wordpress/edit-navigation": "file:packages/edit-navigation",
"@wordpress/edit-post": "file:packages/edit-post",
"@wordpress/edit-site": "file:packages/edit-site",
"@wordpress/edit-widgets": "file:packages/edit-widgets",
diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss
index 28f3a14ac1d95..0e3cf596a24c5 100644
--- a/packages/base-styles/_z-index.scss
+++ b/packages/base-styles/_z-index.scss
@@ -135,7 +135,6 @@ $z-layers: (
".components-popover.interface-more-menu__content": 99998,
".components-popover.block-editor-rich-text__inline-format-toolbar": 99998,
".components-popover.block-editor-warning__dropdown": 99998,
- ".components-popover.edit-navigation-menu-actions__switcher-dropdown": 99998,
".components-autocomplete__results": 1000000,
@@ -170,7 +169,6 @@ $z-layers: (
".components-circular-option-picker__option.is-pressed": 1,
// Needs to be higher than .components-circular-option-picker__option.is-pressed.
".components-circular-option-picker__option.is-pressed + svg": 2,
- ".edit-navigation-layout__overlay": 999,
// Appear under the customizer heading UI, but over anything else.
".customize-widgets__topbar": 8,
diff --git a/packages/block-library/src/navigation/menu-items-to-blocks.js b/packages/block-library/src/navigation/menu-items-to-blocks.js
index 2ffc374978157..00bd4dbbe2a98 100644
--- a/packages/block-library/src/navigation/menu-items-to-blocks.js
+++ b/packages/block-library/src/navigation/menu-items-to-blocks.js
@@ -97,8 +97,6 @@ function mapMenuItemsToBlocks( menuItems, level = 0 ) {
* For more documentation on the individual fields present on a menu item please see:
* https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/nav-menu.php#L789
*
- * Changes made here should also be mirrored in packages/edit-navigation/src/store/utils.js.
- *
* @typedef WPNavMenuItem
*
* @property {Object} title stores the raw and rendered versions of the title/label for this menu item.
diff --git a/packages/e2e-tests/specs/experiments/__snapshots__/navigation-editor.test.js.snap b/packages/e2e-tests/specs/experiments/__snapshots__/navigation-editor.test.js.snap
deleted file mode 100644
index bee7b0da9d1be..0000000000000
--- a/packages/e2e-tests/specs/experiments/__snapshots__/navigation-editor.test.js.snap
+++ /dev/null
@@ -1,39 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Navigation editor allows creation of a menu when there are existing menu items 1`] = `""`;
-
-exports[`Navigation editor allows creation of a menu when there are no current menu items 1`] = `
-"
-
-"
-`;
-
-exports[`Navigation editor displays the first created menu when at least one menu exists 1`] = `
-"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"
-`;
diff --git a/packages/e2e-tests/specs/experiments/navigation-editor.test.js b/packages/e2e-tests/specs/experiments/navigation-editor.test.js
deleted file mode 100644
index be8d9c9a2bdb3..0000000000000
--- a/packages/e2e-tests/specs/experiments/navigation-editor.test.js
+++ /dev/null
@@ -1,850 +0,0 @@
-/**
- * External dependencies
- */
-// eslint-disable-next-line no-restricted-imports
-import { find, findAll } from 'puppeteer-testing-library';
-
-/**
- * WordPress dependencies
- */
-import {
- createJSONResponse,
- createMenu,
- deleteAllMenus,
- pressKeyTimes,
- pressKeyWithModifier,
- setBrowserViewport,
- setUpResponseMocking,
- visitAdminPage,
- __experimentalRest as rest,
-} from '@wordpress/e2e-test-utils';
-import { addQueryArgs } from '@wordpress/url';
-
-/**
- * Internal dependencies
- */
-import { useExperimentalFeatures } from './experimental-features';
-import menuItemsFixture from './fixtures/menu-items-request-fixture.json';
-
-const TYPE_NAMES = {
- post: 'post',
- page: 'page',
- post_tag: 'tag',
- category: 'category',
-};
-
-const searchFixture = [
- {
- id: 300,
- title: 'Home',
- url: 'https://example.com/home',
- type: 'post',
- subtype: 'page',
- },
- {
- id: 301,
- title: 'About',
- url: 'https://example.com/about',
- type: 'post',
- subtype: 'page',
- },
- {
- id: 302,
- title: 'Boats',
- url: 'https://example.com/?cat=123',
- type: 'category',
- },
- {
- id: 303,
- title: 'Faves',
- url: 'https://example.com/?tag=456',
- type: 'post_tag',
- },
-];
-
-// Matching against variations of the same URL encoded and non-encoded
-// produces the most reliable mocking.
-const REST_SEARCH_ROUTES = [
- '/wp/v2/search',
- `rest_route=${ encodeURIComponent( '/wp/v2/search' ) }`,
-];
-
-const REST_PAGES_ROUTES = [
- '/wp/v2/pages',
- `rest_route=${ encodeURIComponent( '/wp/v2/pages' ) }`,
-];
-
-/**
- * Determines if a given URL matches any of a given collection of
- * routes (expressed as substrings).
- *
- * @param {string} reqUrl the full URL to be tested for matches.
- * @param {Array} routes array of strings to match against the URL.
- */
-function matchUrlToRoute( reqUrl, routes ) {
- return routes.some( ( route ) => reqUrl.includes( route ) );
-}
-
-function getEndpointMocks( matchingRoutes, responsesByMethod ) {
- return [ 'GET', 'POST', 'DELETE', 'PUT' ].reduce( ( mocks, restMethod ) => {
- if ( responsesByMethod[ restMethod ] ) {
- return [
- ...mocks,
- {
- match: ( request ) =>
- matchUrlToRoute( request.url(), matchingRoutes ) &&
- request.method() === restMethod,
- onRequestMatch: createJSONResponse(
- responsesByMethod[ restMethod ]
- ),
- },
- ];
- }
-
- return mocks;
- }, [] );
-}
-
-function getSearchMocks( responsesByMethod ) {
- return getEndpointMocks( REST_SEARCH_ROUTES, responsesByMethod );
-}
-
-function getPagesMocks( responsesByMethod ) {
- return getEndpointMocks( REST_PAGES_ROUTES, responsesByMethod );
-}
-
-async function visitNavigationEditor() {
- const query = addQueryArgs( '', {
- page: 'gutenberg-navigation',
- } );
- await visitAdminPage( '/admin.php', query );
-}
-
-/**
- * Get a list of the editor's current blocks for use in a snapshot.
- *
- * @return {string} Block HTML.
- */
-async function getSerializedBlocks() {
- const blocks = await page.evaluate( () =>
- wp.data.select( 'core/block-editor' ).getBlocks()
- );
- const safeBlocks = replaceUnstableBlockAttributes( blocks );
- return page.evaluate(
- ( blocksToSerialize ) => wp.blocks.serialize( blocksToSerialize ),
- safeBlocks
- );
-}
-
-/**
- * Some block attributes contain values that are not stable from test run to
- * test run and can't be compared with a snapshot. These are typically the
- * ids of posts or pages that are created prior to each test run. Replace those
- * values with their types before serializing to a snapshot.
- *
- * @param {Array} blocks The array of block data.
- *
- * @return {Array} Updated array of block data.
- */
-function replaceUnstableBlockAttributes( blocks ) {
- return blocks?.map( ( block ) => {
- const id = block.attributes.id ? typeof block.attributes.id : undefined;
- const url = block.attributes.url
- ? typeof block.attributes.url
- : undefined;
-
- return {
- ...block,
- attributes: {
- ...block.attributes,
- id,
- url,
- },
- innerBlocks: replaceUnstableBlockAttributes( block.innerBlocks ),
- };
- } );
-}
-
-async function deleteAllLinkedResources() {
- [ '/wp/v2/posts', '/wp/v2/pages' ].forEach( async ( path ) => {
- const items = await rest( { path } );
-
- for ( const item of items ) {
- await rest( {
- method: 'DELETE',
- path: `${ path }/${ item.id }?force=true`,
- } );
- }
- } );
-}
-
-async function openMenuActionsDropdown() {
- const menuActionsDropdown = await page.waitForXPath(
- '//*[@role="region"][@aria-label="Navigation top bar"]//*[@class="edit-navigation-menu-actions"]//button[@aria-expanded="false"]'
- );
- await menuActionsDropdown.click();
-}
-
-async function getMenuItem( menuItemName ) {
- return await page
- .waitForXPath(
- `//*[@role="group"]//*[@role="menuitemradio"]/span[text()="${ menuItemName }"]`
- )
- .catch( ( error ) => {
- if ( error.name !== 'TimeoutError' ) {
- throw error;
- } else {
- return null;
- }
- } );
-}
-
-describe.skip( 'Navigation editor', () => {
- useExperimentalFeatures( [ '#gutenberg-navigation' ] );
-
- beforeAll( async () => {
- await deleteAllMenus();
- await deleteAllLinkedResources();
- } );
-
- afterEach( async () => {
- await deleteAllMenus();
- await deleteAllLinkedResources();
- await setUpResponseMocking( [] );
- } );
-
- it( 'allows creation of a menu when there are no current menu items', async () => {
- await visitNavigationEditor();
- await setUpResponseMocking( [
- ...getPagesMocks( {
- GET: [
- {
- type: 'page',
- id: 1,
- link: 'https://example.com/1',
- title: {
- rendered: 'My page',
- },
- },
- ],
- } ),
- ] );
-
- // Wait for the header to show that no menus are available.
- await page.waitForXPath( '//h3[.="Create your first menu"]', {
- visible: true,
- } );
-
- await page.keyboard.type( 'Main Menu' );
- const createMenuButton = await page.waitForXPath(
- '//button[contains(., "Create menu")]'
- );
- await createMenuButton.click();
-
- // A snackbar will appear when menu creation has completed.
- await page.waitForXPath( '//div[contains(., "Menu created")]' );
-
- // Select the navigation block and create a block from existing pages.
- const navigationBlock = await page.waitForSelector(
- 'div[aria-label="Block: Navigation"]'
- );
- await navigationBlock.click();
-
- const addAllPagesButton = await page.waitForXPath(
- '//button[contains(., "Add all pages")]'
- );
- await addAllPagesButton.click();
-
- // When the block is created the root element changes from a div (for the placeholder)
- // to a nav (for the navigation itself). Wait for this to happen.
- await page.waitForSelector( 'nav[aria-label="Block: Navigation"]' );
-
- expect( await getSerializedBlocks() ).toMatchSnapshot();
- } );
-
- it( 'allows creation of a menu when there are existing menu items', async () => {
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
- await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Wait for the header to show the menu name.
- await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
- visible: true,
- } );
-
- const createMenuButton = await page.waitForXPath(
- '//button[.="New menu"]'
- );
- await createMenuButton.click();
-
- const menuNameInputLabel = await page.waitForXPath(
- '//form//label[.="Menu name"]'
- );
- await menuNameInputLabel.click();
-
- await page.keyboard.type( 'New menu' );
- await page.keyboard.press( 'Enter' );
-
- // A snackbar will appear when menu creation has completed.
- await page.waitForXPath( '//div[contains(., "Menu created")]' );
-
- // An empty navigation block will appear.
- await page.waitForSelector( 'div[aria-label="Block: Navigation"]' );
-
- expect( await getSerializedBlocks() ).toMatchSnapshot();
- } );
-
- it( 'displays the first created menu when at least one menu exists', async () => {
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
- await createMenu( { name: 'Test Menu 2' }, menuItemsFixture );
-
- await visitNavigationEditor();
-
- // Wait for the header to show the menu name.
- await page.waitForXPath( '//h2[contains(., "Test Menu 1")]', {
- visible: true,
- } );
-
- // Wait for the block to be present.
- await page.waitForSelector( 'nav[aria-label="Block: Navigation"]' );
-
- expect( await getSerializedBlocks() ).toMatchSnapshot();
- } );
-
- it( 'shows the trailing block appender within the navigation block when no blocks are selected', async () => {
- // The test requires the presence of existing menus.
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Wait for at least one block to be present on the page.
- await page.waitForSelector( '.wp-block' );
-
- // And for this test to be valid, no blocks should be selected, which
- // should be the case when the editor loads.
- const selectedBlocks = await page.$$( '.wp-block.is-selected' );
- expect( selectedBlocks.length ).toBe( 0 );
-
- // And when no blocks are selected, the trailing appender is present.
- const blockListAppender = await page.waitForSelector(
- '.block-list-appender button[aria-label="Add block"]'
- );
- expect( blockListAppender ).toBeTruthy();
- } );
-
- it( 'has a disabled undo button when an existing menu is loaded', async () => {
- // The test requires the presence of existing menus.
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Wait for at least one block to be present on the page.
- await page.waitForSelector( '.wp-block' );
-
- // Check whether there's a disabled undo button.
- const disabledUndoButton = await page.waitForSelector(
- 'button[aria-label="Undo"][aria-disabled="true"]'
- );
- expect( disabledUndoButton ).toBeTruthy();
- } );
-
- it( 'shows a submenu when a link is selected and hides it when clicking the editor to deselect it', async () => {
- await createMenu( { name: 'Test Menu 1' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Select a submenu block with nested links in a submenu.
- const parentLinkXPath =
- '//div[@aria-label="Block: Submenu" and contains(.,"WordPress.org")]';
- const linkBlock = await page.waitForXPath( parentLinkXPath );
- await linkBlock.click();
-
- // There should be a submenu link visible.
- //
- // Submenus are hidden using `visibility: hidden` and shown using
- // `visibility: visible` so the visible/hidden options must be used
- // when selecting the elements.
- const submenuLinkXPath = `${ parentLinkXPath }//div[@aria-label="Block: Custom Link"]`;
- const submenuLinkVisible = await page.waitForXPath( submenuLinkXPath, {
- visible: true,
- } );
- expect( submenuLinkVisible ).toBeDefined();
-
- // Click in the top left corner of the canvas.
- const canvas = await page.$( '.edit-navigation-layout__content-area' );
- const boundingBox = await canvas.boundingBox();
- await page.mouse.click( boundingBox.x + 5, boundingBox.y + 5 );
-
- // There should be a submenu in the DOM, but it should be hidden.
- const submenuLinkHidden = await page.waitForXPath( submenuLinkXPath, {
- hidden: true,
- } );
- expect( submenuLinkHidden ).toBeDefined();
- } );
-
- it( 'displays suggestions when adding a link', async () => {
- await createMenu( { name: 'Test Menu 1' } );
- await setUpResponseMocking( [
- ...getSearchMocks( { GET: searchFixture } ),
- ] );
-
- await visitNavigationEditor();
-
- // Wait for the block to be present and start an empty block.
- const navBlock = await page.waitForSelector(
- 'div[aria-label="Block: Navigation"]'
- );
- await navBlock.click();
- const startEmptyButton = await page.waitForXPath(
- '//button[.="Start blank"]'
- );
- await startEmptyButton.click();
-
- const appender = await page.waitForSelector(
- 'button[aria-label="Add block"]'
- );
- await appender.click();
-
- await page.waitForSelector( 'input[aria-label="URL"]' );
-
- // The link suggestions should be searchable.
- for ( let i = 0; i < searchFixture.length; i++ ) {
- const { title, type, subtype, url } = searchFixture[ i ];
- const expectedURL = url.replace( 'https://', '' );
- const expectedType = TYPE_NAMES[ subtype || type ];
-
- await page.keyboard.type( title );
- const suggestionTitle = await page.waitForXPath(
- `//button[@role="option"]//span[.="${ title }"]`
- );
- const suggestionType = await page.waitForXPath(
- `//button[@role="option"]//span[.="${ expectedType }"]`
- );
- const suggestionURL = await page.waitForXPath(
- `//button[@role="option"]//span[.="${ expectedURL }"]`
- );
- expect( suggestionTitle ).toBeTruthy();
- expect( suggestionType ).toBeTruthy();
- expect( suggestionURL ).toBeTruthy();
- await pressKeyWithModifier( 'primary', 'A' );
- }
- } );
-
- describe( 'Menu name editor', () => {
- const initialMenuName = 'Main Menu';
- const nameEditorSelector = '.edit-navigation-name-editor__text-control';
- const inputSelector = `${ nameEditorSelector } input`;
-
- it( 'saves menu name changes', async () => {
- await createMenu( { name: initialMenuName } );
- await visitNavigationEditor();
-
- // Rename the menu and save it.
- const newName = 'New menu';
- await page.waitForSelector( inputSelector );
- await page.click( inputSelector );
- await pressKeyTimes( 'Backspace', initialMenuName.length );
- await page.keyboard.type( newName );
- await page.click( '.edit-navigation-toolbar__save-button' );
- await page.waitForSelector( '.components-snackbar' );
- await page.reload();
-
- // Expect the header to have the new name.
- const headerSubtitle = await page.waitForSelector(
- '.edit-navigation-menu-actions__subtitle'
- );
- const headerSubtitleText = await headerSubtitle.evaluate(
- ( element ) => element.innerText
- );
- expect( headerSubtitleText ).toBe( newName );
- } );
-
- // Flaky test, see https://github.com/WordPress/gutenberg/pull/34869#issuecomment-922711557.
- it.skip( 'does not save a menu name upon clicking save button when name is empty', async () => {
- await createMenu( { name: initialMenuName } );
- await visitNavigationEditor();
-
- // Try saving a menu with an empty name.
- await page.waitForSelector( inputSelector );
- await page.click( inputSelector );
- await pressKeyTimes( 'Backspace', initialMenuName.length );
- await page.click( '.edit-navigation-toolbar__save-button' );
- const snackbar = await page.waitForSelector(
- '.components-snackbar',
- { visible: true }
- );
- const snackbarText = await snackbar.evaluate(
- ( element ) => element.innerText
- );
- expect( snackbarText ).toBe(
- "Unable to save: 'A name is required for this term.'"
- );
- expect( console ).toHaveErrored(
- 'Failed to load resource: the server responded with a status of 500 (Internal Server Error)'
- );
- await page.reload();
-
- // Expect the header to have the old name.
- const headerSubtitle = await page.waitForSelector(
- '.edit-navigation-menu-actions__subtitle'
- );
- const headerSubtitleText = await headerSubtitle.evaluate(
- ( element ) => element.innerText
- );
- expect( headerSubtitleText ).toBe( initialMenuName );
- } );
- } );
-
- describe( 'Change detections', () => {
- beforeEach( async () => {
- await createMenu( { name: 'Main' } );
- await visitNavigationEditor();
- } );
-
- async function assertIsDirty( isDirty ) {
- let hadDialog = false;
-
- function handleOnDialog() {
- hadDialog = true;
- }
-
- try {
- page.on( 'dialog', handleOnDialog );
- await page.reload();
-
- // Ensure whether it was expected that dialog was encountered.
- expect( hadDialog ).toBe( isDirty );
- } catch ( error ) {
- throw error;
- } finally {
- page.removeListener( 'dialog', handleOnDialog );
- }
- }
-
- // eslint-disable-next-line jest/no-disabled-tests
- it.skip( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => {
- await assertIsDirty( false );
- } );
-
- // eslint-disable-next-line jest/no-disabled-tests
- it.skip( 'should prompt to confirm unsaved changes when menu name is edited', async () => {
- await page.type(
- '.edit-navigation-name-editor__text-control input',
- ' Menu'
- );
-
- await assertIsDirty( true );
- } );
- } );
-
- describe( 'Sidebar inserter', () => {
- it( 'disables inserter toggle when Navigation block is in placeholder state', async () => {
- await createMenu( { name: 'Main Menu' } );
- await visitNavigationEditor();
-
- // Wait for the block to be present.
- await expect( {
- role: 'document',
- name: 'Block: Navigation',
- } ).toBeFound();
-
- // Check for the placeholder state.
- await expect( {
- role: 'button',
- name: 'Start blank',
- } ).toBeFound();
-
- // Expect the block inserter to be disabled.
- await expect( {
- name: 'Toggle block inserter',
- disabled: true,
- role: 'button',
- } ).toBeFound();
- } );
-
- it( 'enables inserter toggle when Navigation block is in editable state', async () => {
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Wait for the block to be present.
- await expect( {
- role: 'document',
- name: 'Block: Navigation',
- } ).toBeFound();
-
- // Expect the block inserter to be found.
- await expect( {
- name: 'Toggle block inserter',
- role: 'button',
- } ).toBeFound();
-
- // Work around bug where `find` with `disabled=false` doesn't return anything.
- const isEnabled = await page.$eval(
- '[aria-label="Toggle block inserter"]',
- ( element ) => ! element.disabled
- );
-
- expect( isEnabled ).toBeTruthy();
- } );
-
- it( 'toggles the inserter sidebar open and closed', async () => {
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
- await visitNavigationEditor();
-
- // Wait for the block to be present.
- await expect( {
- role: 'document',
- name: 'Block: Navigation',
- } ).toBeFound();
-
- // Expect inserter sidebar to **not** be in the DOM.
- await expect( {
- role: 'region',
- name: 'Block library',
- } ).not.toBeFound();
-
- const inserterToggle = await find( {
- name: 'Toggle block inserter',
- role: 'button',
- } );
-
- await inserterToggle.click();
-
- // Expect the inserter sidebar to be present in the DOM.
- await expect( {
- role: 'region',
- name: 'Block library',
- } ).toBeFound();
-
- // Expect block search input to be focused.
- await expect( {
- role: 'searchbox',
- name: 'Search for blocks and patterns',
- focused: true,
- } ).toBeFound();
- } );
-
- it( 'inserts items at end of Navigation block by default', async () => {
- await setUpResponseMocking( [
- ...getSearchMocks( { GET: searchFixture } ),
- ] );
- await createMenu( { name: 'Main Menu' }, menuItemsFixture );
-
- await visitNavigationEditor();
-
- // Wait for the block to be present.
- await expect( {
- role: 'document',
- name: 'Block: Navigation',
- } ).toBeFound();
-
- const inserterToggle = await find( {
- name: 'Toggle block inserter',
- role: 'button',
- } );
-
- await inserterToggle.click();
-
- // Expect the inserter sidebar to be present in the DOM.
- await expect( {
- role: 'region',
- name: 'Block library',
- } ).toBeFound();
-
- // Add Custom Link item.
- const customLinkOption = await find( {
- name: 'Custom Link',
- role: 'option',
- } );
-
- customLinkOption.click();
-
- // Expect that inserter is auto-closed.
- await expect( {
- role: 'region',
- name: 'Block library',
- } ).not.toBeFound();
-
- // Expect to be focused inside the Link UI search input.
- await expect( {
- role: 'combobox',
- name: 'URL',
- focused: true,
- } ).toBeFound();
-
- const [ itemToSelect ] = searchFixture;
-
- // Add Custom Link item.
- const [ firstSearchSuggestion ] = await findAll( {
- role: 'option',
- name: `${ itemToSelect.title } ${ itemToSelect.subtype }`,
- } );
-
- await firstSearchSuggestion.click();
-
- // Get the title/label of the last Nav item inside the Nav block.
- const lastItemAttributes = await page.evaluate( () => {
- const { getBlockOrder, getBlocks } =
- wp.data.select( 'core/block-editor' );
-
- const lockedNavigationBlock = getBlockOrder()[ 0 ];
-
- const navItemBlocks = getBlocks( lockedNavigationBlock );
-
- const { attributes } =
- navItemBlocks[ navItemBlocks.length - 1 ];
-
- return attributes;
- } );
-
- // Check the last item is the one we just inserted.
- expect( lastItemAttributes.label ).toEqual( itemToSelect.title );
- expect( lastItemAttributes.isTopLevelLink ).toBeTruthy();
- } );
- } );
-
- describe( 'Delete menu button', () => {
- useExperimentalFeatures( [ '#gutenberg-navigation' ] );
-
- beforeAll( async () => {
- await deleteAllMenus();
- await deleteAllLinkedResources();
- } );
-
- afterEach( async () => {
- await deleteAllMenus();
- await deleteAllLinkedResources();
- } );
-
- afterEach( async () => {
- await setBrowserViewport( 'large' );
- } );
- it.each( [ 'large', 'small' ] )(
- `should retain menu when confirmation is canceled and the viewport is %s`,
- async ( viewport ) => {
- const menuName = 'Menu delete test';
- await createMenu( { name: menuName }, menuItemsFixture );
- await visitNavigationEditor();
- await setBrowserViewport( viewport );
- // Wait for the header to show the menu name.
- await page.waitForXPath(
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
- );
-
- if ( viewport === 'small' ) {
- const openSettingsSidebar = await page.waitForXPath(
- '//button[@aria-label="Settings"][@aria-expanded="false"]'
- );
- await openSettingsSidebar.click();
- }
-
- const deleteMenuButton = await page.waitForXPath(
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
- );
- await deleteMenuButton.click();
-
- const cancelButton = await page.waitForXPath(
- '//*[@role="dialog"]//button[text()="Cancel"]'
- );
- await cancelButton.click();
-
- const menuActionsDropdown = await page.waitForXPath(
- `//*[contains(@class,"edit-navigation-menu-actions")]//h2[text()="${ menuName }"]`
- );
- const currentSelectedMenu = await page.evaluate(
- ( el ) => el.textContent,
- menuActionsDropdown
- );
-
- expect( currentSelectedMenu ).toBe( menuName );
- }
- );
- it.each( [ 'large', 'small' ] )(
- `should delete menu when confirmation is confirmed and there are no other menus and the viewport is %s`,
- async ( viewport ) => {
- const menuName = 'Menu delete test';
- await createMenu( { name: menuName }, menuItemsFixture );
- await visitNavigationEditor();
- await setBrowserViewport( viewport );
- // Wait for the header to show the menu name.
- await page.waitForXPath(
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
- );
- if ( viewport === 'small' ) {
- const openSettingsSidebar = await page.waitForXPath(
- '//button[@aria-label="Settings"][@aria-expanded="false"]'
- );
- await openSettingsSidebar.click();
- }
-
- const deleteMenuButton = await page.waitForXPath(
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
- );
- await deleteMenuButton.click();
-
- const confirmButton = await page.waitForXPath(
- '//*[@role="dialog"]//button[text()="OK"]'
- );
- await confirmButton.click();
-
- await page.waitForXPath(
- `//*[@role="button"][@aria-label="Dismiss this notice"]//*[text()='"${ menuName }" menu has been deleted']`
- );
-
- // If the "Create your first menu" prompt appears, we know there are no remaining menus,
- // so our test menu must have been deleted successfully.
- const createFirstMenuPrompt = await page.waitForXPath(
- '//h3[.="Create your first menu"]',
- {
- visible: true,
- }
- );
- const noMenusRemaining = createFirstMenuPrompt ? true : false;
- expect( noMenusRemaining ).toBe( true );
- }
- );
-
- it.each( [ 'large', 'small' ] )(
- `should delete menu when confirmation is confirmed and there are other existing menus and the viewport is %s`,
- async () => {
- const menuName = 'Menu delete test';
- await createMenu( { name: menuName }, menuItemsFixture );
- await createMenu(
- { name: `${ menuName } 2` },
- menuItemsFixture
- );
- await visitNavigationEditor();
- // Wait for the header to show the menu name
- await page.waitForXPath(
- `//*[@role="region"][@aria-label="Navigation top bar"]//h2[contains(text(), "${ menuName }")]`
- );
-
- // Confirm both test menus are present
- openMenuActionsDropdown();
- const firstTestMenuItem = await getMenuItem( menuName );
- const secondTestMenuItem = await getMenuItem(
- `${ menuName } 2`
- );
-
- expect( firstTestMenuItem ).not.toBeNull();
- expect( secondTestMenuItem ).not.toBeNull();
-
- // Delete the first test menu
- const deleteMenuButton = await page.waitForXPath(
- '//*[@role="region"][@aria-label="Navigation settings"]//button[text()="Delete menu"]'
- );
- await deleteMenuButton.click();
-
- const confirmButton = await page.waitForXPath(
- '//*[@role="dialog"]//button[text()="OK"]'
- );
- await confirmButton.click();
-
- await page.waitForXPath(
- `//*[@role="button"][@aria-label="Dismiss this notice"]//*[text()='"${ menuName }" menu has been deleted']`
- );
-
- openMenuActionsDropdown();
- const deletedTestMenuItem = await getMenuItem( menuName );
- expect( deletedTestMenuItem ).toBeNull();
- }
- );
- } );
-} );
diff --git a/packages/edit-navigation/.npmrc b/packages/edit-navigation/.npmrc
deleted file mode 100644
index 43c97e719a5a8..0000000000000
--- a/packages/edit-navigation/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-package-lock=false
diff --git a/packages/edit-navigation/CHANGELOG.md b/packages/edit-navigation/CHANGELOG.md
deleted file mode 100644
index 660506373402d..0000000000000
--- a/packages/edit-navigation/CHANGELOG.md
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-## Unreleased
-
-### Bug Fix
-
-- Removed unused `@wordpress/dom-ready`, `@wordpress/media-util`, `rememo` and `uuid` dependencies ([#38388](https://github.com/WordPress/gutenberg/pull/38388)).
-
-### Internal
-
-- Removed `getStablePath` function. Please use `normalizePath` from `@wordpress/url` package instead ([#35992](https://github.com/WordPress/gutenberg/pull/35992)).
-
-## 1.0.0
-
-- Initial version of the package.
diff --git a/packages/edit-navigation/README.md b/packages/edit-navigation/README.md
deleted file mode 100644
index 0f0fd254bb966..0000000000000
--- a/packages/edit-navigation/README.md
+++ /dev/null
@@ -1,188 +0,0 @@
-# Edit navigation
-
-Edit Navigation page module for WordPress - a Gutenberg-based UI for editing navigation menus.
-
-> This package is meant to be used only with WordPress core. Feel free to use it in your own project but please keep in mind that it might never get fully documented.
-
-## Usage
-
-```js
-/**
- * WordPress dependencies
- */
-import { initialize } from '@wordpress/edit-navigation';
-
-/**
- * Internal dependencies
- */
-import blockEditorSettings from './block-editor-settings';
-
-initialize( '#navigation-editor-root', blockEditorSettings );
-```
-
-## Purpose
-
-By default, the Navigation Editor screen allows users to create and edit complex navigations using a block-based UI. The aim is to supersede [the current Menus screen](https://codex.wordpress.org/WordPress_Menu_User_Guide) by providing a superior experience whilst retaining backwards compatibility.
-
-The editing experience is provided as a block editor wrapper around the core functionality of the **Navigation _block_**. Features of the block are disabled/enhanced as necessary to provide an experience appropriate to editing a navigation outside of a Full Site Editing context.
-
-## Modes
-
-The Navigation Editor has two "modes" for _persistence_ ("saving" navigations) and _rendering_:
-
-1. **Classic (default)** - navigations are saved to the _existing_ (post type powered) Menus system and rendered using standard Walker classes.
-2. **Block-based** (opt _in_) - navigations continue to be _saved_ using the existing post type system, but:
- - the [navigation is _rendered_ using the `core/navigation` block](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L228) (as opposed to Walker) to provide access to the full power of blocks (with some tradeoffs in terms of backwards compatibility).
- - non-link blocks (anything that is not `core/navigation-link`) are saved as _blocks_.
-
-### Classic Mode
-
-In this mode, navigations created in the Navigation Editor are stored using the _existing Menu post type_ (`nav_menu_item`) system. As this method matches that used in the _existing_ Menus screen, there is a smooth upgrade path to using new Navigation Editor screen to edit navigations.
-
-Moreover, when the navigation is rendered on the front of the site the system continues to use [the classic Navigation "Walker" class](https://developer.wordpress.org/reference/classes/walker_nav_menu/), thereby ensuring the HTML markup remains the same when using a classic Theme.
-
-### Block-based Mode
-
-**Important**: block-based mode has been temporarily **_disabled_** until it becomes stable. So, if a theme declares support for the `block-nav-menus` feature it will not affect the frontend.
-
-If desired, themes are able to opt into [_rendering_ complete block-based menus](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L228) using the Navigation Editor. This allows for arbitrarily complex navigation block structures to be used in an existing theme whilst still ensuring the navigation data is still _saved_ to the existing (post type powered) Menus system.
-
-Themes can opt into this behaviour by declaring:
-
-```php
-add_theme_support( 'block-nav-menus' );
-```
-
-This unlocks significant additional capabilities in the Navigation Editor. For example, by default, [the Navigation Editor screen only allows _link_ (`core/navigation-link`) blocks to be inserted into a navigation](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js). When a theme opts into `block-nav-menus` however, users are able to add non-link blocks to a navigation using the Navigation Editor screen, including:
-
-- `core/navigation-link`.
-- `core/social`.
-- `core/search`.
-
-As these items are still saved to `nav_menu_items` this ensures if we ever revert to classic (Walker-based) rendering, these items will still be rendered (as blocks).
-
-## Backwards compatibility
-
-By design the underlying systems of the Nav Editor screen should be largely backwards compatible with the existing Menus screen. Therefore any navigations created or edited using the new Navigation Editor screen should continue to work in the existing classic Menus screen.
-
-Currently, the only exception to this would be any custom functionality added (by Plugins or otherwise) to the existing Menus screen would not be replicated in the new Navigation Editor screen. In this scenario there might be danger of some data loss.
-
-### Downgrading from block-based to classic Themes
-
-If the user switches to a theme that does not support block menus, or disables this functionality, ~non-link blocks are no longer rendered on the frontend~ [block-based links will still be rendered on the front end](https://github.com/WordPress/gutenberg/blob/7310097da5e16159b79e6e039a2cb3812cb9055e/lib/navigation.php#L104-L135). Care is also taken to ensure that users can still see their data on the existing Menus screen.
-
-## Block to Menu Item mapping
-
-The Navigation Editor needs to be able to map navigation items in two directions:
-
-1. `nav_menu_item`s to Blocks - when displaying an existing navigation.
-2. Blocks to `nav_menu_item`s - when _saving_ an navigation being editing in the Navigation screen.
-
-The Navigation Editor has two dedicated methods for handling mapping between these two expressions of the data:
-
-- [`menuItemToBlockAttributes()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L261-L313).
-- [`blockAttributestoMenuItem()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L184-L253)
-
-To understand these fully, one must appreciate that WordPress maps raw `nav_menu_item` posts to [Menu item _objects_](https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/nav-menu.php#L786). These have various properties which map as follows:
-
-| Menu Item object property | Equivalent Block Attribute | Description |
-| :------------------------ | :----------------------------------------------------: | :-------------------------------------------------------------------------------------------------------: |
-| `ID` | Not mapped. | The term_id if the menu item represents a taxonomy term. |
-| `attr_title` | `title` | The title attribute of the link element for this menu item. |
-| `classes` | `classNames` | The array of class attribute values for the link element of this menu item. |
-| `db_id` | Not mapped. | The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). |
-| `description` | `description` | The description of this menu item. |
-| `menu_item_parent` | Not mapped.[1](#menu_item_menu_item_parent) | The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. |
-| `object` | `type` | The type of object originally represented, such as 'category', 'post', or 'attachment'. |
-| `object_id` | `id` | The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. |
-| `post_parent` | Not mapped. | The DB ID of the original object's parent object, if any (0 otherwise). |
-| `post_title` | Not mapped. | A "no title" label if menu item represents a post that lacks a title. |
-| `target` | `opensInNewTab`[2](#menu_item_target) | The target attribute of the link element for this menu item. |
-| `title` | `label` | The title of this menu item. |
-| `type` | `kind` | The family of objects originally represented, such as 'post_type' or 'taxonomy'. |
-| `type_label` | Not mapped. | The singular label used to describe this type of menu item. |
-| `url` | `url` | The URL to which this menu item points. |
-| `xfn` | `rel` | The XFN relationship expressed in the link of this menu item. |
-| `\_invalid` | Not mapped. | Whether the menu item represents an object that no longer exists. |
-
-- [1] - the parent -> child relationship is expressed in block via the `innerBlocks` attribute and is therefore not required as a explicit block attribute.
-- [2] - applies only if the value of the `target` field is `_blank`.
-
-### Inconsistencies
-
-#### Mapping
-
-For historical reasons, the following properties display some inconsistency in their mapping from Menu Item Object to Block attribute:
-
-- `type` -> `kind` - the family of objects is stored as `kind` on the block and so must be mapped accordingly.
-- `object` -> `type` - the type of object is stored as `type` on the block and so must be mapped accordingly.
-- `object_id` -> `id` - the block stores a reference to the original object's ID as the `id` _attribute_. This should not be confused with the block's `clientId` which is unrelated.
-- `attr_title` -> `title` - the HTML `title` attribute is stored as `title` on the block and so must be mapped accordingly.
-
-#### Object Types
-
-- Menu Item objects which represent "Tags" are stored in WordPress as `post_tag` but the block expects their `type` attribute to be `tag` (omiting the `post_` suffix). This inconsistency is accounted for in [the mapping utilities methods](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L279-L281).
-
-## Hooks
-
-The `useNavigationEditor` and `useEntityBlockEditor` hooks are the central part of this package. They bridge the gap between the API and the block editor interface:
-
-```jsx
-// Data from API:
-const {
- menus,
- hasLoadedMenus,
- selectedMenuId,
- navigationPost,
-} = useNavigationEditor();
-
-// Working state:
-const [ blocks, onInput, onChange ] = useEntityBlockEditor(
- NAVIGATION_POST_KIND,
- NAVIGATION_POST_POST_TYPE,
- {
- id: navigationPost?.id,
- }
-);
-
-const isBlockEditorReady = !! (
- menus?.length &&
- navigationPost &&
- selectedMenuId
-);
-
-return (
-
- { isBlockEditorReady && (
-
-
-
-
-
- ) }
-
-);
-```
-
-## Glossary
-
-- **(Navigation) link** - the basic `core/navigation-link` block which is the standard block used to add links within navigations.
-- **Block-based link** - any navigation item that is _not_ a `core/navigation-link` block. These are persisted as blocks but still utilise the existing Menus post type system.
-- **Navigation block** - the root `core/navigation` block which can be used both with the Navigation Editor and outside (eg: Post / Site Editor).
-- **Navigation editor / screen** - the new screen provided by Gutenberg to allow the user to edit navigations using a block-based UI.
-- **Menus screen** - the current/existing [interface/screen for managing Menus](https://codex.wordpress.org/WordPress_Menu_User_Guide) in WordPress WPAdmin.
-
-_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._
-
-## 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/edit-navigation/docs/README.md b/packages/edit-navigation/docs/README.md
deleted file mode 100644
index f55b91dc44a7b..0000000000000
--- a/packages/edit-navigation/docs/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Documentation
-
-This folder contains documentations for the Navigation Editor.
-
-1. [User Documentation](./user-documentation.md)
diff --git a/packages/edit-navigation/docs/user-documentation.md b/packages/edit-navigation/docs/user-documentation.md
deleted file mode 100644
index d12a1bb78cb2d..0000000000000
--- a/packages/edit-navigation/docs/user-documentation.md
+++ /dev/null
@@ -1,86 +0,0 @@
-Note: this documentation is a work in progress.
-
-# Block-based navigation editor
-
-The Block-based Navigation Editor brings the power of blocks to the Appearance > Navigation section in the WordPress Administration Screens allowing you use blocks to create menus.
-
-## How to use the editor
-
-The interface replicates the Post Editor experience, allowing you to use similar workflows like drag and drop.
-
-The editor provides access to any menus created using the previous Menus screen in WordPress.
-
-New menus can easily be created, options are provided to do so in a few different ways:
-* from an existing page hierarchy
-* by copying an existing menu
-* by creating a blank menu
-
-
-Rather than the paragraph being the go-to block, the Navigation Editor provides a link block for creating links to different types of items. Page, post, tag, category and custom links can all be created. Links can be nested to create sub-menus.
-
-### How to create a menu
-
-1. At the top of the editor select 'New menu'.
-2. Type the name of your menu.
-3. Choose a starting option of either 'Start blank', 'Add all pages', or 'Copy existing menu'.
-
-### How to insert a link
-
-If you'd like to link to a page, post, tag, or category:
-
-1. Click one of the `+` buttons.
-2. Select the type of link you want to add.
-3. Use the dialog to search for the item you want to link to.
-
-For a custom link:
-
-1. Click one of the `+` buttons.
-2. Select the 'Custom Link' block.
-3. Using the dialog that appears, type in a URL and press 'Enter'.
-
-### How to insert a submenu
-
-There are two ways to insert a submenu.
-
-The first option is to create a new submenu from scratch:
-
-1. Click one of the `+` buttons.
-2. Select the 'Submenu' block.
-3. (Optional) Add a URL for the submenu.
-4. Use the nested `+` button in the submenu to add blocks in the submenu
-
-Alternatively, an existing link can be converted into a submenu:
-
-1. Select an existing link block.
-2. From the toolbar, select the 'Add submenu' button.
-
-### How to rename a menu
-
-1. If the settings sidebar isn't visible, click the 'Settings' button in the top-right corner of the screen.
-2. Select the 'Menu' tab.
-3. Use the name field at the top of the sidebar to rename a menu.
-4. Save any changes.
-
-### Assigning a menu to a theme location
-
-A theme location designates the part of your site that a menu is displayed. To assign, change or unassign a theme location.
-
-1. If the settings sidebar isn't visible, click the 'Settings' button in the top-right corner of the screen.
-2. Select the 'Menu' tab.
-3. Use the Theme Locations panel to select which locations the menu should be assigned to.
-4. Save any changes.
-
-For an overview of which menus are assigned to which locations, use the 'Manage locations' button in the same part of the screen.
-
-### Deleting a menu
-
-1. Choose a menu to delete using the menu selector in the middle of the editor's header.
-2. If the settings sidebar isn't visible, click the 'Settings' button in the top-right corner of the screen.
-3. Select the 'Menu' tab.
-4. Click the 'Delete menu' button.
-
-### How to opt-in or out of using the block-based navigation editor
-
-1. From WordPress admin, select the Gutenberg > Experiments option.
-2. Uncheck the tickbox to disable the editor or check it to enable it.
-3. Save changes.
diff --git a/packages/edit-navigation/package.json b/packages/edit-navigation/package.json
deleted file mode 100644
index ea504ea09bd06..0000000000000
--- a/packages/edit-navigation/package.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "name": "@wordpress/edit-navigation",
- "version": "1.9.22",
- "private": true,
- "description": "Module for the Navigation page in WordPress.",
- "author": "The WordPress Contributors",
- "license": "GPL-2.0-or-later",
- "keywords": [
- "wordpress",
- "gutenberg",
- "editor",
- "navigation"
- ],
- "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/edit-navigation/README.md",
- "repository": {
- "type": "git",
- "url": "https://github.com/WordPress/gutenberg.git",
- "directory": "packages/edit-navigation"
- },
- "bugs": {
- "url": "https://github.com/WordPress/gutenberg/issues"
- },
- "engines": {
- "node": ">=12"
- },
- "main": "build/index.js",
- "module": "build-module/index.js",
- "react-native": "src/index",
- "dependencies": {
- "@babel/runtime": "^7.16.0",
- "@wordpress/api-fetch": "file:../api-fetch",
- "@wordpress/block-editor": "file:../block-editor",
- "@wordpress/block-library": "file:../block-library",
- "@wordpress/blocks": "file:../blocks",
- "@wordpress/components": "file:../components",
- "@wordpress/compose": "file:../compose",
- "@wordpress/core-data": "file:../core-data",
- "@wordpress/data": "file:../data",
- "@wordpress/dom": "file:../dom",
- "@wordpress/element": "file:../element",
- "@wordpress/hooks": "file:../hooks",
- "@wordpress/html-entities": "file:../html-entities",
- "@wordpress/i18n": "file:../i18n",
- "@wordpress/icons": "file:../icons",
- "@wordpress/interface": "file:../interface",
- "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts",
- "@wordpress/keycodes": "file:../keycodes",
- "@wordpress/notices": "file:../notices",
- "@wordpress/plugins": "file:../plugins",
- "@wordpress/preferences": "file:../preferences",
- "@wordpress/url": "file:../url",
- "classnames": "^2.3.1",
- "lodash": "^4.17.21"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/packages/edit-navigation/src/components/add-menu/index.js b/packages/edit-navigation/src/components/add-menu/index.js
deleted file mode 100644
index 936aed5d9b3b5..0000000000000
--- a/packages/edit-navigation/src/components/add-menu/index.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * External dependencies
- */
-import classnames from 'classnames';
-
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { useState, useEffect } from '@wordpress/element';
-import { useSelect, useDispatch } from '@wordpress/data';
-import { Button, TextControl, withNotices } from '@wordpress/components';
-import { useFocusOnMount } from '@wordpress/compose';
-import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
-import { store as noticesStore } from '@wordpress/notices';
-import { store as coreStore } from '@wordpress/core-data';
-
-/**
- * Internal dependencies
- */
-import { MENU_POST_TYPE, MENU_KIND } from '../../constants';
-
-function AddMenu( {
- className,
- onCreate,
- titleText,
- helpText,
- focusInputOnMount = false,
- noticeUI,
- noticeOperations,
-} ) {
- const inputRef = useFocusOnMount( focusInputOnMount );
- const [ menuName, setMenuName ] = useState( '' );
- const [ isCreatingMenu, setIsCreatingMenu ] = useState( false );
- const { createInfoNotice } = useDispatch( noticesStore );
- const { saveMenu } = useDispatch( coreStore );
-
- const { createErrorNotice, removeAllNotices } = noticeOperations;
-
- const lastSaveError = useSelect( ( select ) => {
- return select( coreStore ).getLastEntitySaveError(
- MENU_KIND,
- MENU_POST_TYPE
- );
- }, [] );
-
- useEffect( () => {
- if ( lastSaveError ) {
- createErrorNotice( stripHTML( lastSaveError?.message ) );
- }
- }, [ lastSaveError ] );
-
- const createMenu = async ( event ) => {
- event.preventDefault();
-
- if ( ! menuName.length || isCreatingMenu ) {
- return;
- }
-
- setIsCreatingMenu( true );
-
- // Remove any existing notices.
- removeAllNotices();
-
- const menu = await saveMenu( { name: menuName } );
-
- setIsCreatingMenu( false );
-
- if ( menu ) {
- createInfoNotice( __( 'Menu created' ), {
- type: 'snackbar',
- isDismissible: true,
- } );
- if ( onCreate ) {
- onCreate( menu.id );
- }
- }
- };
-
- return (
-
- );
-}
-
-export default withNotices( AddMenu );
diff --git a/packages/edit-navigation/src/components/add-menu/style.scss b/packages/edit-navigation/src/components/add-menu/style.scss
deleted file mode 100644
index 835fb912545a0..0000000000000
--- a/packages/edit-navigation/src/components/add-menu/style.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.edit-navigation-add-menu {
- display: flex;
- flex-direction: column;
-
- // Notices.
- .components-with-notices-ui {
- margin-bottom: $grid-unit-20;
-
- // Notice is too big with default styles.
- .components-notice {
- margin: 0;
- padding: $grid-unit-10 $grid-unit-15;
- }
-
- .components-notice__content {
- margin: 0;
- }
- }
-}
-
-.edit-navigation-add-menu__title {
- margin-top: 0;
-}
-
-.edit-navigation-add-menu__create-menu-button {
- align-self: flex-end;
-}
diff --git a/packages/edit-navigation/src/components/block-placeholder/index.js b/packages/edit-navigation/src/components/block-placeholder/index.js
deleted file mode 100644
index 48c2171dd4916..0000000000000
--- a/packages/edit-navigation/src/components/block-placeholder/index.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { createBlock } from '@wordpress/blocks';
-import {
- Placeholder,
- Button,
- DropdownMenu,
- MenuGroup,
- MenuItem,
- Spinner,
-} from '@wordpress/components';
-import {
- forwardRef,
- useCallback,
- useState,
- useEffect,
-} from '@wordpress/element';
-import { __ } from '@wordpress/i18n';
-import { chevronDown } from '@wordpress/icons';
-
-/**
- * Internal dependencies
- */
-import { useMenuEntityProp, useSelectedMenuId } from '../../hooks';
-import useNavigationEntities from './use-navigation-entities';
-import { menuItemsToBlocks } from '../../store/transform';
-
-/**
- * Convert pages to blocks.
- *
- * @param {Object[]} pages An array of pages.
- *
- * @return {WPBlock[]} An array of blocks.
- */
-function convertPagesToBlocks( pages ) {
- if ( ! pages?.length ) {
- return null;
- }
-
- return pages.map( ( { title, type, link: url, id } ) =>
- createBlock( 'core/navigation-link', {
- type,
- id,
- url,
- label: ! title.rendered ? __( '(no title)' ) : title.rendered,
- opensInNewTab: false,
- } )
- );
-}
-
-const TOGGLE_PROPS = { variant: 'tertiary' };
-const POPOVER_PROPS = { position: 'bottom center' };
-
-function BlockPlaceholder( { onCreate }, ref ) {
- const [ selectedMenu, setSelectedMenu ] = useState();
- const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false );
-
- const [ selectedMenuId ] = useSelectedMenuId();
- const [ menuName ] = useMenuEntityProp( 'name', selectedMenuId );
-
- const {
- isResolvingPages,
- menus,
- isResolvingMenus,
- menuItems,
- hasResolvedMenuItems,
- pages,
- hasPages,
- hasMenus,
- } = useNavigationEntities( selectedMenu );
-
- const isLoading = isResolvingPages || isResolvingMenus;
-
- const createFromMenu = useCallback( () => {
- const { innerBlocks: blocks } = menuItemsToBlocks( menuItems );
- const selectNavigationBlock = true;
- onCreate( blocks, selectNavigationBlock );
- }, [ menuItems, menuItemsToBlocks, onCreate ] );
-
- const onCreateFromMenu = () => {
- // If we have menu items, create the block right away.
- if ( hasResolvedMenuItems ) {
- createFromMenu();
- return;
- }
-
- // Otherwise, create the block when resolution finishes.
- setIsCreatingFromMenu( true );
- };
-
- const onCreateEmptyMenu = () => {
- onCreate( [] );
- };
-
- const onCreateAllPages = () => {
- const blocks = convertPagesToBlocks( pages );
- const selectNavigationBlock = true;
- onCreate( blocks, selectNavigationBlock );
- };
-
- useEffect( () => {
- // If the user selected a menu but we had to wait for menu items to
- // finish resolving, then create the block once resolution finishes.
- if ( isCreatingFromMenu && hasResolvedMenuItems ) {
- createFromMenu();
- setIsCreatingFromMenu( false );
- }
- }, [ isCreatingFromMenu, hasResolvedMenuItems ] );
-
- const selectableMenus = menus?.filter(
- ( menu ) => menu.id !== selectedMenuId
- );
-
- const hasSelectableMenus = !! selectableMenus?.length;
-
- return (
-
-