From ce1220a4b8c9e7138c00ae3a18acae9898d8d7fb Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Wed, 1 Feb 2023 14:56:07 +0100 Subject: [PATCH] support custom list item props on search extensions Co-authored-by: Camila Belo Signed-off-by: Emma Indal --- docs/features/search/how-to-guides.md | 14 +++++++++ plugins/catalog/api-report.md | 3 +- plugins/catalog/src/plugin.ts | 7 +++-- plugins/explore/api-report.md | 3 +- plugins/explore/src/plugin.ts | 7 +++-- plugins/search-react/api-report.md | 11 +++++++ plugins/search-react/src/extensions.tsx | 39 +++++++++++++++---------- plugins/techdocs/api-report.md | 3 +- plugins/techdocs/src/plugin.ts | 7 +++-- 9 files changed, 70 insertions(+), 24 deletions(-) diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 6f113630f6..b464168724 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -235,6 +235,20 @@ export const YourSearchResultListItemExtension = plugin.provide( ); ``` +If your list item accept props, you can extend the `SearchResultListItemExtensionProps` with your component specific props: + +```tsx +export const YourSearchResultListItemExtension: ( + props: SearchResultListItemExtensionProps, +) => JSX.Element | null = plugin.provide( + createSearchResultListItemExtension({ + name: 'YourSearchResultListItem', + component: () => + import('./components').then(m => m.YourSearchResultListItem), + }), +); +``` + Additionally, you can define a predicate function that receives a result and returns whether your extension should be used to render it or not: ```tsx diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 901120bd22..6d746f6a7c 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { StarredEntitiesApi } from '@backstage/plugin-catalog-react'; import { StorageApi } from '@backstage/core-plugin-api'; import { StyleRules } from '@material-ui/core/styles/withStyles'; @@ -108,7 +109,7 @@ export const catalogPlugin: BackstagePlugin< // @public (undocumented) export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 12c22eb537..ea6ddcaff2 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -31,7 +31,10 @@ import { fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { DefaultStarredEntitiesApi } from './apis'; import { AboutCardProps } from './components/AboutCard'; import { DefaultCatalogPageProps } from './components/CatalogPage'; @@ -254,7 +257,7 @@ export const RelatedEntitiesCard: ( /** @public */ export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = catalogPlugin.provide( createSearchResultListItemExtension({ name: 'CatalogSearchResultListItem', diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index e7adde4b77..da960ae951 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -19,6 +19,7 @@ import { IndexableDocument } from '@backstage/plugin-search-common'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TabProps } from '@material-ui/core'; // @public @deprecated (undocumented) @@ -126,7 +127,7 @@ export const ToolExplorerContent: (props: { // @public (undocumented) export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/explore/src/plugin.ts b/plugins/explore/src/plugin.ts index 5a4bec53c5..84e7657355 100644 --- a/plugins/explore/src/plugin.ts +++ b/plugins/explore/src/plugin.ts @@ -22,7 +22,10 @@ import { discoveryApiRef, fetchApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { ExploreClient, exploreApiRef } from './api'; import { ToolSearchResultListItemProps } from './components/ToolSearchResultListItem'; // import { exampleTools } from './util/examples'; @@ -70,7 +73,7 @@ export const explorePlugin = createPlugin({ /** @public */ export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = explorePlugin.provide( createSearchResultListItemExtension({ name: 'ToolSearchResultListItem', diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index 0d6598feca..375af20d5c 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -14,6 +14,7 @@ import { InputBaseProps } from '@material-ui/core'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { LinkProps } from '@backstage/core-components'; +import { ListItemProps } from '@material-ui/core'; import { ListItemTextProps } from '@material-ui/core'; import { ListProps } from '@material-ui/core'; import { PropsWithChildren } from 'react'; @@ -392,6 +393,16 @@ export type SearchResultListItemExtensionOptions< predicate?: (result: SearchResult_2) => boolean; }; +// @public +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; + // @public export const SearchResultListItemExtensions: ( props: SearchResultListItemExtensionsProps, diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index 30611b0879..6c854e24e0 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -33,7 +33,7 @@ import { } from '@backstage/core-plugin-api'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; -import { ListItem, List, ListProps } from '@material-ui/core'; +import { ListItem, List, ListProps, ListItemProps } from '@material-ui/core'; import { DefaultResultListItem } from './components'; @@ -73,26 +73,34 @@ const findSearchResultListItemExtensionElement = ( }; /** - * @internal - * Props for {@link SearchResultListItemExtension}. + * @public + * Extends props for any search result list item extension */ -type SearchResultListItemExtensionProps = PropsWithChildren<{ - rank?: number; - result?: SearchDocument; - noTrack?: boolean; -}>; +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; /** * @internal * Extends children with extension capabilities. * @param props - see {@link SearchResultListItemExtensionProps}. */ -const SearchResultListItemExtension = ({ - rank, - result, - noTrack, - children, -}: SearchResultListItemExtensionProps) => { +const SearchResultListItemExtension = ( + props: SearchResultListItemExtensionProps, +) => { + const { + rank, + result, + noTrack, + children, + alignItems = 'flex-start', + ...rest + } = props; const analytics = useAnalytics(); const handleClickCapture = useCallback(() => { @@ -107,8 +115,9 @@ const SearchResultListItemExtension = ({ return ( {children} diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index ddc90d07bb..9452b38feb 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TableColumn } from '@backstage/core-components'; import { TableOptions } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; @@ -400,7 +401,7 @@ export type TechDocsSearchProps = { // @public export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 331eefe121..bdd4814898 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -33,7 +33,10 @@ import { fetchApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem'; /** @@ -162,7 +165,7 @@ export const TechDocsReaderPage = techdocsPlugin.provide( * @public */ export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = techdocsPlugin.provide( createSearchResultListItemExtension({ name: 'TechDocsSearchResultListItem',