Skip to content

Commit 6ad1848

Browse files
feat(docsearch): add hitComponent and transformItems options
1 parent a86a368 commit 6ad1848

3 files changed

Lines changed: 43 additions & 22 deletions

File tree

src/DocSearch.tsx

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ import {
1414
} from './types';
1515
import { createSearchClient, groupBy, noop } from './utils';
1616
import { createStoredSearches } from './stored-searches';
17+
import { Hit } from './Hit';
1718
import { SearchBox } from './SearchBox';
1819
import { ScreenState } from './ScreenState';
1920
import { Footer } from './Footer';
2021

2122
interface DocSearchProps
22-
extends Omit<
23-
PublicAutocompleteOptions<InternalDocSearchHit>,
24-
'onStateChange' | 'getSources'
25-
> {
23+
extends Pick<PublicAutocompleteOptions<InternalDocSearchHit>, 'navigator'> {
2624
appId?: string;
2725
apiKey: string;
2826
indexName: string;
29-
searchParameters: any;
30-
onClose(): void;
27+
searchParameters?: any;
28+
onClose?(): void;
29+
transformItems?(items: DocSearchHit[]): DocSearchHit[];
30+
hitComponent?(props: {
31+
hit: DocSearchHit;
32+
children: React.ReactNode;
33+
}): JSX.Element;
3134
}
3235

3336
export function DocSearch({
@@ -36,7 +39,9 @@ export function DocSearch({
3639
indexName,
3740
searchParameters,
3841
onClose = noop,
39-
...autocompleteProps
42+
transformItems = x => x,
43+
hitComponent = Hit,
44+
navigator,
4045
}: DocSearchProps) {
4146
const [state, setState] = React.useState<
4247
AutocompleteState<InternalDocSearchHit>
@@ -107,7 +112,7 @@ export function DocSearch({
107112
initialState: {
108113
query: initialQuery,
109114
},
110-
...autocompleteProps,
115+
navigator,
111116
onStateChange({ state }) {
112117
setState(state as any);
113118
},
@@ -191,17 +196,7 @@ export function DocSearch({
191196
throw error;
192197
})
193198
.then((hits: DocSearchHit[]) => {
194-
const formattedHits = hits.map(hit => {
195-
const url = new URL(hit.url);
196-
return {
197-
...hit,
198-
url: hit.url
199-
// @TODO: temporary convenience for development.
200-
.replace(url.origin, '')
201-
.replace('#__docusaurus', ''),
202-
};
203-
});
204-
const sources = groupBy(formattedHits, hit => hit.hierarchy.lvl0);
199+
const sources = groupBy(hits, hit => hit.hierarchy.lvl0);
205200

206201
// We store the `lvl0`s to display them as search suggestions
207202
// in the “no results“ screen.
@@ -224,6 +219,7 @@ export function DocSearch({
224219
return Object.values(
225220
groupBy(items, item => item.hierarchy.lvl1)
226221
)
222+
.map(transformItems)
227223
.map(hits =>
228224
hits.map(item => {
229225
return {
@@ -256,6 +252,8 @@ export function DocSearch({
256252
favoriteSearches,
257253
saveRecentSearch,
258254
initialQuery,
255+
navigator,
256+
transformItems,
259257
]
260258
);
261259

@@ -338,6 +336,7 @@ export function DocSearch({
338336
<ScreenState
339337
{...autocomplete}
340338
state={state}
339+
hitComponent={hitComponent}
341340
recentSearches={recentSearches}
342341
favoriteSearches={favoriteSearches}
343342
onItemClick={item => {

src/Hit.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
3+
import { DocSearchHit } from './types';
4+
5+
interface HitProps {
6+
hit: DocSearchHit;
7+
children: React.ReactNode;
8+
}
9+
10+
export function Hit({ hit, children }: HitProps) {
11+
return <a href={hit.url}>{children}</a>;
12+
}

src/Results.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import {
44
AutocompleteState,
55
} from '@francoischalifour/autocomplete-core';
66

7-
import { StoredDocSearchHit, InternalDocSearchHit } from './types';
7+
import {
8+
DocSearchHit,
9+
InternalDocSearchHit,
10+
StoredDocSearchHit,
11+
} from './types';
812
import { Snippet } from './Snippet';
913

1014
interface ResultsProps<TItem>
@@ -19,6 +23,10 @@ interface ResultsProps<TItem>
1923
renderIcon(props: { item: TItem; index: number }): React.ReactNode;
2024
renderAction(props: { item: TItem }): React.ReactNode;
2125
onItemClick(item: TItem): void;
26+
hitComponent(props: {
27+
hit: DocSearchHit;
28+
children: React.ReactNode;
29+
}): JSX.Element;
2230
}
2331

2432
export function Results<TItem extends StoredDocSearchHit>(
@@ -28,6 +36,8 @@ export function Results<TItem extends StoredDocSearchHit>(
2836
return null;
2937
}
3038

39+
const Hit = props.hitComponent;
40+
3141
return (
3242
<section className="DocSearch-Hits">
3343
<div className="DocSearch-Hit-source">{props.title}</div>
@@ -52,7 +62,7 @@ export function Results<TItem extends StoredDocSearchHit>(
5262
},
5363
})}
5464
>
55-
<a href={item.url}>
65+
<Hit hit={item}>
5666
<div className="DocSearch-Hit-Container">
5767
{props.renderIcon({ item, index })}
5868

@@ -110,7 +120,7 @@ export function Results<TItem extends StoredDocSearchHit>(
110120

111121
{props.renderAction({ item })}
112122
</div>
113-
</a>
123+
</Hit>
114124
</li>
115125
);
116126
})}

0 commit comments

Comments
 (0)