Skip to content

Commit fbd9e72

Browse files
feat(plugin): add transformSource API
This updates the plugins' API to allow complete source override, as opposed to only templates override. ## Why Users might want to override the behavior of the original source (e.g., keep the panel open on select). This wasn't possible with the previous API, which only allow to modify the template. ## API ```tsx const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ key: 'search', limit: 3, transformSource({ source, onRemove }) { return { ...source, getItemUrl({ item }) { return `https://google.com?q=${item.query}`; }, }; }, }); const querySuggestionsPlugin = createQuerySuggestionsPlugin({ searchClient, indexName: 'instant_search_demo_query_suggestions', transformSource({ source, onTapAhead }) { return { ...source, onSelect({ setIsOpen }) { setIsOpen(true); }, getItemUrl({ item }) { return `https://google.com?q=${item.query}`; }, templates: { ...source.templates, item(params) { const { item } = params; return ( <a href={`https://google.com?q=${item.query}`} className="aa-ItemLink" > {source.templates.item(params)} </a> ); }, }, }; }, }); ```
1 parent 9bc826e commit fbd9e72

File tree

6 files changed

+227
-63
lines changed

6 files changed

+227
-63
lines changed

packages/autocomplete-plugin-query-suggestions/src/createQuerySuggestionsPlugin.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@ import {
22
AutocompletePlugin,
33
AutocompleteState,
44
} from '@algolia/autocomplete-core';
5-
import { getAlgoliaHits, SourceTemplates } from '@algolia/autocomplete-js';
5+
import { AutocompleteSource, getAlgoliaHits } from '@algolia/autocomplete-js';
66
import { SearchOptions } from '@algolia/client-search';
77
import { SearchClient } from 'algoliasearch/lite';
88

9-
import {
10-
getTemplates as defaultGetTemplates,
11-
GetTemplatesParams,
12-
} from './getTemplates';
9+
import { getTemplates } from './getTemplates';
1310
import { QuerySuggestionsHit } from './types';
1411

1512
export type CreateQuerySuggestionsPluginParams<
@@ -18,7 +15,10 @@ export type CreateQuerySuggestionsPluginParams<
1815
searchClient: SearchClient;
1916
indexName: string;
2017
getSearchParams?(params: { state: AutocompleteState<TItem> }): SearchOptions;
21-
getTemplates?(params: GetTemplatesParams<TItem>): SourceTemplates<TItem>;
18+
transformSource?(params: {
19+
source: AutocompleteSource<TItem>;
20+
onTapAhead(item: TItem): void;
21+
}): AutocompleteSource<TItem>;
2222
};
2323

2424
export function createQuerySuggestionsPlugin<
@@ -27,38 +27,43 @@ export function createQuerySuggestionsPlugin<
2727
searchClient,
2828
indexName,
2929
getSearchParams = () => ({}),
30-
getTemplates = defaultGetTemplates,
30+
transformSource = ({ source }) => source,
3131
}: CreateQuerySuggestionsPluginParams<TItem>): AutocompletePlugin<
3232
TItem,
3333
undefined
3434
> {
3535
return {
3636
getSources({ query, setQuery, refresh, state }) {
37+
function onTapAhead(item: TItem) {
38+
setQuery(item.query);
39+
refresh();
40+
}
41+
42+
const templates = getTemplates({ onTapAhead });
43+
3744
return [
38-
{
39-
sourceId: 'querySuggestionsPlugin',
40-
getItemInputValue({ item }) {
41-
return item.query;
42-
},
43-
getItems() {
44-
return getAlgoliaHits<TItem>({
45-
searchClient,
46-
queries: [
47-
{
48-
indexName,
49-
query,
50-
params: getSearchParams({ state }),
51-
},
52-
],
53-
});
54-
},
55-
templates: getTemplates({
56-
onTapAhead(item) {
57-
setQuery(item.query);
58-
refresh();
45+
transformSource({
46+
source: {
47+
sourceId: 'querySuggestionsPlugin',
48+
getItemInputValue({ item }) {
49+
return item.query;
50+
},
51+
getItems() {
52+
return getAlgoliaHits<TItem>({
53+
searchClient,
54+
queries: [
55+
{
56+
indexName,
57+
query,
58+
params: getSearchParams({ state }),
59+
},
60+
],
61+
});
5962
},
60-
}),
61-
},
63+
templates,
64+
},
65+
onTapAhead,
66+
}),
6267
];
6368
},
6469
};

packages/autocomplete-plugin-recent-searches/src/createLocalStorageRecentSearchesPlugin.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ export type CreateRecentSearchesLocalStorageOptions<
3838

3939
type LocalStorageRecentSearchesPluginOptions<
4040
TItem extends RecentSearchesItem
41-
> = Pick<CreateRecentSearchesPluginParams<TItem>, 'getTemplates'> &
41+
> = Pick<CreateRecentSearchesPluginParams<TItem>, 'transformSource'> &
4242
CreateRecentSearchesLocalStorageOptions<TItem>;
4343

4444
export function createLocalStorageRecentSearchesPlugin<
4545
TItem extends RecentSearchesItem
4646
>({
4747
key,
4848
limit = 5,
49-
getTemplates,
49+
transformSource,
5050
search = defaultSearch,
5151
}: LocalStorageRecentSearchesPluginOptions<TItem>): AutocompletePlugin<
5252
TItem,
@@ -59,7 +59,7 @@ export function createLocalStorageRecentSearchesPlugin<
5959
});
6060

6161
return createRecentSearchesPlugin({
62-
getTemplates,
62+
transformSource,
6363
storage,
6464
});
6565
}

packages/autocomplete-plugin-recent-searches/src/createRecentSearchesPlugin.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
import { AutocompletePlugin } from '@algolia/autocomplete-core';
2-
import { SourceTemplates } from '@algolia/autocomplete-js';
3-
import { MaybePromise, warn } from '@algolia/autocomplete-shared';
2+
import { AutocompleteSource } from '@algolia/autocomplete-js';
3+
import { createRef, MaybePromise, warn } from '@algolia/autocomplete-shared';
44
import { SearchOptions } from '@algolia/client-search';
55

66
import { createStore, RecentSearchesStorage } from './createStore';
7-
import {
8-
getTemplates as defaultGetTemplates,
9-
GetTemplatesParams,
10-
} from './getTemplates';
7+
import { getTemplates } from './getTemplates';
118
import { RecentSearchesItem } from './types';
129

13-
type Ref<TType> = {
14-
current: TType;
15-
};
16-
1710
export type RecentSearchesPluginData = {
1811
getAlgoliaSearchParams(params?: SearchOptions): SearchOptions;
1912
};
@@ -22,18 +15,21 @@ export type CreateRecentSearchesPluginParams<
2215
TItem extends RecentSearchesItem
2316
> = {
2417
storage: RecentSearchesStorage<TItem>;
25-
getTemplates?(params: GetTemplatesParams): SourceTemplates<TItem>;
18+
transformSource?(params: {
19+
source: AutocompleteSource<TItem>;
20+
onRemove(id: string): void;
21+
}): AutocompleteSource<TItem>;
2622
};
2723

2824
export function createRecentSearchesPlugin<TItem extends RecentSearchesItem>({
2925
storage,
30-
getTemplates = defaultGetTemplates,
26+
transformSource = ({ source }) => source,
3127
}: CreateRecentSearchesPluginParams<TItem>): AutocompletePlugin<
3228
TItem,
3329
RecentSearchesPluginData
3430
> {
35-
const store = createStore<TItem>(storage);
36-
const lastItemsRef: Ref<MaybePromise<TItem[]>> = { current: [] };
31+
const store = createStore(storage);
32+
const lastItemsRef = createRef<MaybePromise<TItem[]>>([]);
3733

3834
return {
3935
subscribe({ onSelect }) {
@@ -44,7 +40,7 @@ export function createRecentSearchesPlugin<TItem extends RecentSearchesItem>({
4440
store.add({
4541
id: inputValue,
4642
query: inputValue,
47-
} as TItem);
43+
} as any);
4844
}
4945
});
5046
},
@@ -55,33 +51,38 @@ export function createRecentSearchesPlugin<TItem extends RecentSearchesItem>({
5551
store.add({
5652
id: query,
5753
query,
58-
} as TItem);
54+
} as any);
5955
}
6056
},
6157
getSources({ query, refresh }) {
6258
lastItemsRef.current = store.getAll(query);
6359

60+
function onRemove(id: string) {
61+
store.remove(id);
62+
refresh();
63+
}
64+
65+
const templates = getTemplates<any>({ onRemove });
66+
6467
return Promise.resolve(lastItemsRef.current).then((items) => {
6568
if (items.length === 0) {
6669
return [];
6770
}
6871

6972
return [
70-
{
71-
sourceId: 'recentSearchesPlugin',
72-
getItemInputValue({ item }) {
73-
return item.query;
74-
},
75-
getItems() {
76-
return items;
77-
},
78-
templates: getTemplates({
79-
onRemove(id) {
80-
store.remove(id);
81-
refresh();
73+
transformSource({
74+
source: {
75+
sourceId: 'recentSearchesPlugin',
76+
getItemInputValue({ item }) {
77+
return item.query;
8278
},
83-
}),
84-
},
79+
getItems() {
80+
return items;
81+
},
82+
templates,
83+
},
84+
onRemove,
85+
}),
8586
];
8687
});
8788
},

packages/website/docs/createLocalStorageRecentSearchesPlugin.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,58 @@ function search({ query, items, limit }) {
110110
}
111111
```
112112

113+
### `transformSource`
114+
115+
> `(params: { source: AutocompleteSource, onRemove: () => void })`
116+
117+
#### Example
118+
119+
Keeping the panel open on select:
120+
121+
```tsx
122+
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
123+
key: 'navbar',
124+
transformSource({ source, onRemove }) {
125+
return {
126+
...source,
127+
onSelect({ setIsOpen }) {
128+
setIsOpen(true);
129+
},
130+
};
131+
},
132+
});
133+
```
134+
135+
Opening a link:
136+
137+
```tsx
138+
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
139+
key: 'navbar',
140+
transformSource({ source, onRemove }) {
141+
return {
142+
...source,
143+
getItemUrl({ item }) {
144+
return `https://google.com?q=${item.query}`;
145+
},
146+
templates: {
147+
...source.templates,
148+
item(params) {
149+
const { item } = params;
150+
return (
151+
<a
152+
className="aa-ItemLink"
153+
href={`https://google.com?q=${item.query}`}
154+
>
155+
{source.templates.item(params)}
156+
</a>
157+
);
158+
},
159+
},
160+
};
161+
},
162+
});
163+
```
164+
113165
## Returns
114166

115167
### `data`

packages/website/docs/createQuerySuggestionsPlugin.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,57 @@ import { createQuerySuggestionsPlugin } from '@algolia/autocomplete-plugin-query
7373
### `getSearchParams`
7474

7575
> [`() => SearchParameters`](https://www.algolia.com/doc/api-reference/search-api-parameters/)
76+
77+
### `transformSource`
78+
79+
> `(params: { source: AutocompleteSource, onTapAhead: () => void })`
80+
81+
#### Example
82+
83+
Keeping the panel open on select:
84+
85+
```tsx
86+
const querySuggestionsPlugin = createQuerySuggestionsPlugin({
87+
searchClient,
88+
indexName: 'instant_search_demo_query_suggestions',
89+
transformSource({ source, onTapAhead }) {
90+
return {
91+
...source,
92+
onSelect({ setIsOpen }) {
93+
setIsOpen(true);
94+
},
95+
};
96+
},
97+
});
98+
```
99+
100+
Opening a link:
101+
102+
```tsx
103+
const querySuggestionsPlugin = createQuerySuggestionsPlugin({
104+
searchClient,
105+
indexName: 'instant_search_demo_query_suggestions',
106+
transformSource({ source, onTapAhead }) {
107+
return {
108+
...source,
109+
getItemUrl({ item }) {
110+
return `https://google.com?q=${item.query}`;
111+
},
112+
templates: {
113+
...source.templates,
114+
item(params) {
115+
const { item } = params;
116+
return (
117+
<a
118+
className="aa-ItemLink"
119+
href={`https://google.com?q=${item.query}`}
120+
>
121+
{source.templates.item(params)}
122+
</a>
123+
);
124+
},
125+
},
126+
};
127+
},
128+
});
129+
```

0 commit comments

Comments
 (0)