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,