Skip to content

Commit

Permalink
Move hook to core-data
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Dec 21, 2023
1 parent cc80345 commit 15f78d9
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 168 deletions.
93 changes: 92 additions & 1 deletion packages/core-data/src/fetch/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,93 @@
export { default as __experimentalFetchLinkSuggestions } from './__experimental-fetch-link-suggestions';
/**
* WordPress dependencies
*/
import { useCallback } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { store as coreStore } from '../';
import { default as fetchLinkSuggestions } from './__experimental-fetch-link-suggestions';

export const __experimentalFetchLinkSuggestions = fetchLinkSuggestions;
export { default as __experimentalFetchUrlData } from './__experimental-fetch-url-data';

export function __experimentalUseLinkControlEntitySearch() {
const settings = useSelect(
( select ) => select( blockEditorStore ).getSettings(),
[]
);
// The function should either be undefined or a stable function reference
// throughout the editor lifetime, much like importing a function from a
// module.
const { pageOnFront, pageForPosts } = useSelect( ( select ) => {
const { canUser, getEntityRecord } = select( coreStore );

const siteSettings = canUser( 'read', 'settings' )
? getEntityRecord( 'root', 'site' )
: undefined;

return {
pageOnFront: siteSettings?.page_on_front,
pageForPosts: siteSettings?.page_for_posts,
};
}, [] );

return useCallback(
async ( val, suggestionsQuery, withCreateSuggestion ) => {
const { isInitialSuggestions } = suggestionsQuery;

const results = await fetchLinkSuggestions(
val,
suggestionsQuery,
settings
);

// Identify front page and update type to match.
results.map( ( result ) => {
if ( Number( result.id ) === pageOnFront ) {
result.isFrontPage = true;
return result;
} else if ( Number( result.id ) === pageForPosts ) {
result.isBlogHome = true;
return result;
}

return result;
} );

// If displaying initial suggestions just return plain results.
if ( isInitialSuggestions ) {
return results;
}

// Here we append a faux suggestion to represent a "CREATE" option. This
// is detected in the rendering of the search results and handled as a
// special case. This is currently necessary because the suggestions
// dropdown will only appear if there are valid suggestions and
// therefore unless the create option is a suggestion it will not
// display in scenarios where there are no results returned from the
// API. In addition promoting CREATE to a first class suggestion affords
// the a11y benefits afforded by `URLInput` to all suggestions (eg:
// keyboard handling, ARIA roles...etc).
//
// Note also that the value of the `title` and `url` properties must correspond
// to the text value of the `<input>`. This is because `title` is used
// when creating the suggestion. Similarly `url` is used when using keyboard to select
// the suggestion (the <form> `onSubmit` handler falls-back to `url`).
return ! withCreateSuggestion
? results
: results.concat( {
// the `id` prop is intentionally ommitted here because it
// is never exposed as part of the component's public API.
// see: https://github.com/WordPress/gutenberg/pull/19775#discussion_r378931316.
title: val, // Must match the existing `<input>`s text value.
url: val, // Must match the existing `<input>`s text value.
type: '__CREATE__',
} );
},
[ pageOnFront, pageForPosts, settings ]
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ import {
useEntityBlockEditor,
store as coreStore,
useResourcePermissions,
__experimentalFetchLinkSuggestions as fetchLinkSuggestions,
__experimentalUseLinkControlEntitySearch as useLinkControlEntitySearch,
} from '@wordpress/core-data';
import { useMemo, useCallback } from '@wordpress/element';
import {
privateApis as blockEditorPrivateApis,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useMemo } from '@wordpress/element';
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns';
import { store as preferencesStore } from '@wordpress/preferences';

Expand All @@ -34,84 +31,6 @@ const { ExperimentalBlockEditorProvider, settingsKeys } = unlock(
);
const { PatternsMenuItems } = unlock( editPatternsPrivateApis );

function useLinkControlEntitySearch() {
const settings = useSelect(
( select ) => select( blockEditorStore ).getSettings(),
[]
);
// The function should either be undefined or a stable function reference
// throughout the editor lifetime, much like importing a function from a
// module.
const { pageOnFront, pageForPosts } = useSelect( ( select ) => {
const { canUser, getEntityRecord } = select( coreStore );

const siteSettings = canUser( 'read', 'settings' )
? getEntityRecord( 'root', 'site' )
: undefined;

return {
pageOnFront: siteSettings?.page_on_front,
pageForPosts: siteSettings?.page_for_posts,
};
}, [] );

return useCallback(
async ( val, suggestionsQuery, withCreateSuggestion ) => {
const { isInitialSuggestions } = suggestionsQuery;

const results = await fetchLinkSuggestions(
val,
suggestionsQuery,
settings
);

// Identify front page and update type to match.
results.map( ( result ) => {
if ( Number( result.id ) === pageOnFront ) {
result.isFrontPage = true;
return result;
} else if ( Number( result.id ) === pageForPosts ) {
result.isBlogHome = true;
return result;
}

return result;
} );

// If displaying initial suggestions just return plain results.
if ( isInitialSuggestions ) {
return results;
}

// Here we append a faux suggestion to represent a "CREATE" option. This
// is detected in the rendering of the search results and handled as a
// special case. This is currently necessary because the suggestions
// dropdown will only appear if there are valid suggestions and
// therefore unless the create option is a suggestion it will not
// display in scenarios where there are no results returned from the
// API. In addition promoting CREATE to a first class suggestion affords
// the a11y benefits afforded by `URLInput` to all suggestions (eg:
// keyboard handling, ARIA roles...etc).
//
// Note also that the value of the `title` and `url` properties must correspond
// to the text value of the `<input>`. This is because `title` is used
// when creating the suggestion. Similarly `url` is used when using keyboard to select
// the suggestion (the <form> `onSubmit` handler falls-back to `url`).
return ! withCreateSuggestion
? results
: results.concat( {
// the `id` prop is intentionally ommitted here because it
// is never exposed as part of the component's public API.
// see: https://github.com/WordPress/gutenberg/pull/19775#discussion_r378931316.
title: val, // Must match the existing `<input>`s text value.
url: val, // Must match the existing `<input>`s text value.
type: '__CREATE__',
} );
},
[ pageOnFront, pageForPosts, settings ]
);
}

export default function WidgetAreasBlockEditorProvider( {
blockEditorSettings,
children,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import { Platform, useMemo, useCallback } from '@wordpress/element';
import { useDispatch, useSelect } from '@wordpress/data';
import {
store as coreStore,
__experimentalFetchLinkSuggestions as fetchLinkSuggestions,
__experimentalUseLinkControlEntitySearch as useLinkControlEntitySearch,
__experimentalFetchUrlData as fetchUrlData,
} from '@wordpress/core-data';
import { __ } from '@wordpress/i18n';
import {
privateApis as blockEditorPrivateApis,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';

/**
* Internal dependencies
Expand Down Expand Up @@ -85,84 +82,6 @@ const BLOCK_EDITOR_SETTINGS = [
'__experimentalArchiveTitleNameLabel',
];

function useLinkControlEntitySearch() {
const settings = useSelect(
( select ) => select( blockEditorStore ).getSettings(),
[]
);
// The function should either be undefined or a stable function reference
// throughout the editor lifetime, much like importing a function from a
// module.
const { pageOnFront, pageForPosts } = useSelect( ( select ) => {
const { canUser, getEntityRecord } = select( coreStore );

const siteSettings = canUser( 'read', 'settings' )
? getEntityRecord( 'root', 'site' )
: undefined;

return {
pageOnFront: siteSettings?.page_on_front,
pageForPosts: siteSettings?.page_for_posts,
};
}, [] );

return useCallback(
async ( val, suggestionsQuery, withCreateSuggestion ) => {
const { isInitialSuggestions } = suggestionsQuery;

const results = await fetchLinkSuggestions(
val,
suggestionsQuery,
settings
);

// Identify front page and update type to match.
results.map( ( result ) => {
if ( Number( result.id ) === pageOnFront ) {
result.isFrontPage = true;
return result;
} else if ( Number( result.id ) === pageForPosts ) {
result.isBlogHome = true;
return result;
}

return result;
} );

// If displaying initial suggestions just return plain results.
if ( isInitialSuggestions ) {
return results;
}

// Here we append a faux suggestion to represent a "CREATE" option. This
// is detected in the rendering of the search results and handled as a
// special case. This is currently necessary because the suggestions
// dropdown will only appear if there are valid suggestions and
// therefore unless the create option is a suggestion it will not
// display in scenarios where there are no results returned from the
// API. In addition promoting CREATE to a first class suggestion affords
// the a11y benefits afforded by `URLInput` to all suggestions (eg:
// keyboard handling, ARIA roles...etc).
//
// Note also that the value of the `title` and `url` properties must correspond
// to the text value of the `<input>`. This is because `title` is used
// when creating the suggestion. Similarly `url` is used when using keyboard to select
// the suggestion (the <form> `onSubmit` handler falls-back to `url`).
return ! withCreateSuggestion
? results
: results.concat( {
// the `id` prop is intentionally ommitted here because it
// is never exposed as part of the component's public API.
// see: https://github.com/WordPress/gutenberg/pull/19775#discussion_r378931316.
title: val, // Must match the existing `<input>`s text value.
url: val, // Must match the existing `<input>`s text value.
type: '__CREATE__',
} );
},
[ pageOnFront, pageForPosts, settings ]
);
}

/**
* React hook used to compute the block editor settings to use for the post editor.
*
Expand Down

0 comments on commit 15f78d9

Please sign in to comment.