diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js
index bffeb929c921e7..c9dee401164a76 100644
--- a/packages/block-editor/src/components/link-control/index.js
+++ b/packages/block-editor/src/components/link-control/index.js
@@ -181,6 +181,7 @@ function LinkControl( {
hasTextControl = false,
renderControlBottom = null,
handleEntities = false,
+ showCreateSuggestionInDropdown,
} ) {
if ( withCreateSuggestion === undefined && createSuggestion ) {
withCreateSuggestion = true;
@@ -711,6 +712,9 @@ function LinkControl( {
helpTextId={ helpTextId }
/>
}
+ showCreateSuggestionInDropdown={
+ showCreateSuggestionInDropdown
+ }
/>
{ isEntity && helpTextId && (
{
+ backButtonRef.current?.focus();
+ }, [] );
+
+ const handleTitleChange = ( newTitle ) => {
+ setTitle( newTitle );
+ if ( ! isSlugDirty ) {
+ setSlug( generateSlug( newTitle ) );
+ }
+ };
+
+ const handleSlugChange = ( newSlug ) => {
+ setSlug( newSlug );
+ setIsSlugDirty( true );
+ };
+
+ const handleCreate = async () => {
+ if ( ! title?.trim() ) {
+ return;
+ }
+
+ setIsCreating( true );
+ setErrorMessage( null );
+ try {
+ const suggestion = await onCreateSuggestion(
+ title.trim(),
+ publishImmediately,
+ slug.trim()
+ );
+ if ( suggestion?.url ) {
+ onPageCreated( suggestion );
+ }
+ } catch ( _e ) {
+ setErrorMessage(
+ __( 'There was an error creating the page. Please try again.' )
+ );
+ setIsCreating( false );
+ }
+ };
+
+ return (
+
+
+
+ { errorMessage && (
+
+ { errorMessage }
+
+ ) }
+
+ {
+ if ( event.key === 'Enter' ) {
+ event.preventDefault();
+ handleCreate();
+ }
+ } }
+ disabled={ isCreating }
+ />
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/block-editor/src/components/link-control/search-input.js b/packages/block-editor/src/components/link-control/search-input.js
index c72e7f69166ce6..2f7f894f43aad4 100644
--- a/packages/block-editor/src/components/link-control/search-input.js
+++ b/packages/block-editor/src/components/link-control/search-input.js
@@ -3,7 +3,10 @@
*/
import { forwardRef, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
+import { plus } from '@wordpress/icons';
+import { Button } from '@wordpress/components';
import deprecated from '@wordpress/deprecated';
+import { LinkControlPageCreator } from './page-creator';
/**
* Internal dependencies
@@ -46,13 +49,14 @@ const LinkControlSearchInput = forwardRef(
suffix,
isEntity = false,
customValidity: customValidityProp,
+ showCreateSuggestionInDropdown = false,
},
ref
) => {
const genericSearchHandler = useSearchHandler(
suggestionsQuery,
allowDirectEntry,
- withCreateSuggestion,
+ withCreateSuggestion && showCreateSuggestionInDropdown,
withURLSuggestion
);
@@ -61,6 +65,7 @@ const LinkControlSearchInput = forwardRef(
: noopSearchHandler;
const [ focusedSuggestion, setFocusedSuggestion ] = useState();
+ const [ isCreatingPage, setIsCreatingPage ] = useState( false );
/**
* Handles the user moving between different suggestions. Does not handle
@@ -129,6 +134,17 @@ const LinkControlSearchInput = forwardRef(
? _placeholder
: __( 'Link' );
+ if ( withCreateSuggestion && isCreatingPage ) {
+ return (
+ setIsCreatingPage( false ) }
+ onCancel={ () => setIsCreatingPage( false ) }
+ />
+ );
+ }
+
return (
+ { withCreateSuggestion && ! showCreateSuggestionInDropdown && (
+
+ ) }
{ children }
);
diff --git a/packages/block-editor/src/components/link-control/style.scss b/packages/block-editor/src/components/link-control/style.scss
index 061ac588c3d774..abd0881612c3e4 100644
--- a/packages/block-editor/src/components/link-control/style.scss
+++ b/packages/block-editor/src/components/link-control/style.scss
@@ -56,6 +56,22 @@ $block-editor-link-control-number-of-actions: 1;
}
}
}
+
+ &__page-creator {
+ max-width: 350px;
+ min-width: auto;
+ width: 90vw;
+ padding-top: $grid-unit-10;
+
+ &__back {
+ margin-left: $grid-unit-10;
+ text-transform: uppercase;
+ }
+
+ &__inner {
+ padding: $grid-unit-20;
+ }
+ }
}
// Provides positioning context for reset button. Without this then when an
@@ -304,6 +320,21 @@ $block-editor-link-control-number-of-actions: 1;
.block-editor-link-control__search-create {
align-items: center; // align text with icon.
+ width: 100%;
+ border-top: 1px solid $gray-200;
+ padding: $grid-unit-10 $grid-unit-15;
+ color: $gray-900;
+
+ &:hover,
+ &:focus {
+ background-color: $gray-100;
+ }
+
+ mark {
+ font-weight: 600;
+ color: inherit;
+ background-color: transparent;
+ }
.block-editor-link-control__preview-title {
margin-bottom: 0;
diff --git a/packages/block-editor/src/components/link-control/use-create-page.js b/packages/block-editor/src/components/link-control/use-create-page.js
index 42e243a2625fd4..1816eecb4c9986 100644
--- a/packages/block-editor/src/components/link-control/use-create-page.js
+++ b/packages/block-editor/src/components/link-control/use-create-page.js
@@ -9,7 +9,11 @@ export default function useCreatePage( handleCreatePage ) {
const [ isCreatingPage, setIsCreatingPage ] = useState( false );
const [ errorMessage, setErrorMessage ] = useState( null );
- const createPage = async function ( suggestionTitle ) {
+ const createPage = async function (
+ suggestionTitle,
+ publishImmediately,
+ Slug
+ ) {
setIsCreatingPage( true );
setErrorMessage( null );
@@ -19,7 +23,13 @@ export default function useCreatePage( handleCreatePage ) {
cancelableCreateSuggestion.current = makeCancelable(
// Using Promise.resolve to allow createSuggestion to return a
// non-Promise based value.
- Promise.resolve( handleCreatePage( suggestionTitle ) )
+ Promise.resolve(
+ handleCreatePage(
+ suggestionTitle,
+ publishImmediately,
+ Slug
+ )
+ )
);
return await cancelableCreateSuggestion.current.promise;
diff --git a/packages/block-library/src/button/edit.js b/packages/block-library/src/button/edit.js
index b89580164178f9..b2b40263d1bd5b 100644
--- a/packages/block-library/src/button/edit.js
+++ b/packages/block-library/src/button/edit.js
@@ -204,11 +204,16 @@ function ButtonEdit( props ) {
[ context, isSelected, metadata?.bindings?.url ]
);
- async function handleCreate( pageTitle ) {
- const page = await createPageEntity( {
+ async function handleCreate( pageTitle, publishImmediately, Slug ) {
+ const payload = {
title: pageTitle,
- status: 'draft',
- } );
+ status: publishImmediately ? 'publish' : 'draft',
+ };
+
+ if ( Slug ) {
+ payload.slug = Slug;
+ }
+ const page = await createPageEntity( payload );
return {
id: page.id,
diff --git a/packages/format-library/src/link/inline.js b/packages/format-library/src/link/inline.js
index 9b9129be340713..40e7eea9ee1aee 100644
--- a/packages/format-library/src/link/inline.js
+++ b/packages/format-library/src/link/inline.js
@@ -251,11 +251,16 @@ function InlineLinkUI( {
},
} );
- async function handleCreate( pageTitle ) {
- const page = await createPageEntity( {
+ async function handleCreate( pageTitle, publishImmediately, Slug ) {
+ const payload = {
title: pageTitle,
- status: 'draft',
- } );
+ status: publishImmediately ? 'publish' : 'draft',
+ };
+
+ if ( Slug ) {
+ payload.slug = Slug;
+ }
+ const page = await createPageEntity( payload );
return {
id: page.id,