diff --git a/src/DocSearch.tsx b/src/DocSearch.tsx index 7ec87cd31..b52a5fb86 100644 --- a/src/DocSearch.tsx +++ b/src/DocSearch.tsx @@ -14,20 +14,23 @@ import { } from './types'; import { createSearchClient, groupBy, noop } from './utils'; import { createStoredSearches } from './stored-searches'; +import { Hit } from './Hit'; import { SearchBox } from './SearchBox'; import { ScreenState } from './ScreenState'; import { Footer } from './Footer'; interface DocSearchProps - extends Omit< - PublicAutocompleteOptions, - 'onStateChange' | 'getSources' - > { + extends Pick, 'navigator'> { appId?: string; apiKey: string; indexName: string; - searchParameters: any; - onClose(): void; + searchParameters?: any; + onClose?(): void; + transformItems?(items: DocSearchHit[]): DocSearchHit[]; + hitComponent?(props: { + hit: DocSearchHit; + children: React.ReactNode; + }): JSX.Element; } export function DocSearch({ @@ -36,7 +39,9 @@ export function DocSearch({ indexName, searchParameters, onClose = noop, - ...autocompleteProps + transformItems = x => x, + hitComponent = Hit, + navigator, }: DocSearchProps) { const [state, setState] = React.useState< AutocompleteState @@ -107,7 +112,7 @@ export function DocSearch({ initialState: { query: initialQuery, }, - ...autocompleteProps, + navigator, onStateChange({ state }) { setState(state as any); }, @@ -191,17 +196,7 @@ export function DocSearch({ throw error; }) .then((hits: DocSearchHit[]) => { - const formattedHits = hits.map(hit => { - const url = new URL(hit.url); - return { - ...hit, - url: hit.url - // @TODO: temporary convenience for development. - .replace(url.origin, '') - .replace('#__docusaurus', ''), - }; - }); - const sources = groupBy(formattedHits, hit => hit.hierarchy.lvl0); + const sources = groupBy(hits, hit => hit.hierarchy.lvl0); // We store the `lvl0`s to display them as search suggestions // in the “no results“ screen. @@ -224,6 +219,7 @@ export function DocSearch({ return Object.values( groupBy(items, item => item.hierarchy.lvl1) ) + .map(transformItems) .map(hits => hits.map(item => { return { @@ -256,6 +252,8 @@ export function DocSearch({ favoriteSearches, saveRecentSearch, initialQuery, + navigator, + transformItems, ] ); @@ -338,6 +336,7 @@ export function DocSearch({ { diff --git a/src/Hit.tsx b/src/Hit.tsx new file mode 100644 index 000000000..09e539ee5 --- /dev/null +++ b/src/Hit.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +import { DocSearchHit } from './types'; + +interface HitProps { + hit: DocSearchHit; + children: React.ReactNode; +} + +export function Hit({ hit, children }: HitProps) { + return {children}; +} diff --git a/src/Results.tsx b/src/Results.tsx index 566f1cf18..83ca0b206 100644 --- a/src/Results.tsx +++ b/src/Results.tsx @@ -4,7 +4,11 @@ import { AutocompleteState, } from '@francoischalifour/autocomplete-core'; -import { StoredDocSearchHit, InternalDocSearchHit } from './types'; +import { + DocSearchHit, + InternalDocSearchHit, + StoredDocSearchHit, +} from './types'; import { Snippet } from './Snippet'; interface ResultsProps @@ -19,6 +23,10 @@ interface ResultsProps renderIcon(props: { item: TItem; index: number }): React.ReactNode; renderAction(props: { item: TItem }): React.ReactNode; onItemClick(item: TItem): void; + hitComponent(props: { + hit: DocSearchHit; + children: React.ReactNode; + }): JSX.Element; } export function Results( @@ -28,6 +36,8 @@ export function Results( return null; } + const Hit = props.hitComponent; + return (
{props.title}
@@ -52,7 +62,7 @@ export function Results( }, })} > - +
{props.renderIcon({ item, index })} @@ -110,7 +120,7 @@ export function Results( {props.renderAction({ item })}
-
+ ); })}